diff --git a/hardware/digistump/avr/libraries/DigisparkIRLib/.gitattributes b/hardware/digistump/avr/libraries/DigisparkIRLib/.gitattributes new file mode 100644 index 0000000..412eeda --- /dev/null +++ b/hardware/digistump/avr/libraries/DigisparkIRLib/.gitattributes @@ -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 diff --git a/hardware/digistump/avr/libraries/DigisparkIRLib/.gitignore b/hardware/digistump/avr/libraries/DigisparkIRLib/.gitignore new file mode 100644 index 0000000..b9d6bd9 --- /dev/null +++ b/hardware/digistump/avr/libraries/DigisparkIRLib/.gitignore @@ -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 diff --git a/hardware/digistump/avr/libraries/DigisparkIRLib/CHANGELOG.txt b/hardware/digistump/avr/libraries/DigisparkIRLib/CHANGELOG.txt new file mode 100644 index 0000000..72ac377 --- /dev/null +++ b/hardware/digistump/avr/libraries/DigisparkIRLib/CHANGELOG.txt @@ -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 \ No newline at end of file diff --git a/hardware/digistump/avr/libraries/DigisparkIRLib/IRLib.cpp b/hardware/digistump/avr/libraries/DigisparkIRLib/IRLib.cpp new file mode 100644 index 0000000..66013a7 --- /dev/null +++ b/hardware/digistump/avr/libraries/DigisparkIRLib/IRLib.cpp @@ -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 + + +/* + * 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 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 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 +// 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 + + +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 diff --git a/hardware/digistump/avr/libraries/DigisparkIRLib/IRLib.h b/hardware/digistump/avr/libraries/DigisparkIRLib/IRLib.h new file mode 100644 index 0000000..f6b1445 --- /dev/null +++ b/hardware/digistump/avr/libraries/DigisparkIRLib/IRLib.h @@ -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 + +// 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 diff --git a/hardware/digistump/avr/libraries/DigisparkIRLib/IRLibMatch.h b/hardware/digistump/avr/libraries/DigisparkIRLib/IRLibMatch.h new file mode 100644 index 0000000..fa70ea2 --- /dev/null +++ b/hardware/digistump/avr/libraries/DigisparkIRLib/IRLibMatch.h @@ -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 diff --git a/hardware/digistump/avr/libraries/DigisparkIRLib/IRLibTimer.h b/hardware/digistump/avr/libraries/DigisparkIRLib/IRLibTimer.h new file mode 100644 index 0000000..842a514 --- /dev/null +++ b/hardware/digistump/avr/libraries/DigisparkIRLib/IRLibTimer.h @@ -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<> 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 diff --git a/hardware/digistump/avr/libraries/DigisparkIRLib/LICENSE.txt b/hardware/digistump/avr/libraries/DigisparkIRLib/LICENSE.txt new file mode 100644 index 0000000..1a3c3c4 Binary files /dev/null and b/hardware/digistump/avr/libraries/DigisparkIRLib/LICENSE.txt differ diff --git a/hardware/digistump/avr/libraries/DigisparkIRLib/README.txt b/hardware/digistump/avr/libraries/DigisparkIRLib/README.txt new file mode 100644 index 0000000..da47d1e --- /dev/null +++ b/hardware/digistump/avr/libraries/DigisparkIRLib/README.txt @@ -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. diff --git a/hardware/digistump/avr/libraries/DigisparkIRLib/examples/DigiIrDump/DigiIrDump.ino b/hardware/digistump/avr/libraries/DigisparkIRLib/examples/DigiIrDump/DigiIrDump.ino new file mode 100644 index 0000000..23bb3ec --- /dev/null +++ b/hardware/digistump/avr/libraries/DigisparkIRLib/examples/DigiIrDump/DigiIrDump.ino @@ -0,0 +1,84 @@ +#include // 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 // 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 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(); +} + diff --git a/hardware/digistump/avr/libraries/DigisparkIRLib/examples/DigiIrRgbCtrl/DigiIrRgbCtrl.ino b/hardware/digistump/avr/libraries/DigisparkIRLib/examples/DigiIrRgbCtrl/DigiIrRgbCtrl.ino new file mode 100644 index 0000000..17f6149 --- /dev/null +++ b/hardware/digistump/avr/libraries/DigisparkIRLib/examples/DigiIrRgbCtrl/DigiIrRgbCtrl.ino @@ -0,0 +1,201 @@ +#include +#include +/* + _____ ____ __ _ ____ _ _ _ _ + | __ \ / __ \ | \ | | / __ \ | | | | | | | | + | |__| | | / \_| | . \ | | / / \ \ | | | | \ \ / / + | _ / | | _ | |\ \| | | |__| | | | | | \ ' / + | | \ \ | \__/ | | | \ ' | | __ | \ \/ / | | + |_| \_\ \____/ |_| \__| |_| |_| \__/ |_| 2013 + + http://p.loussouarn.free.fr + + ************************************************* + * Optimized 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; + } + } +} + diff --git a/hardware/digistump/avr/libraries/DigisparkIRLib/examples/IRhashdecode/IRhashdecode.ino b/hardware/digistump/avr/libraries/DigisparkIRLib/examples/IRhashdecode/IRhashdecode.ino new file mode 100644 index 0000000..d1e00b7 --- /dev/null +++ b/hardware/digistump/avr/libraries/DigisparkIRLib/examples/IRhashdecode/IRhashdecode.ino @@ -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 + +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 + } +} + diff --git a/hardware/digistump/avr/libraries/DigisparkIRLib/examples/IRrecord/IRrecord.ino b/hardware/digistump/avr/libraries/DigisparkIRLib/examples/IRrecord/IRrecord.ino new file mode 100644 index 0000000..12d7f61 --- /dev/null +++ b/hardware/digistump/avr/libraries/DigisparkIRLib/examples/IRrecord/IRrecord.ino @@ -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 + +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(); + } +} + diff --git a/hardware/digistump/avr/libraries/DigisparkIRLib/examples/IRrecvDump/IRrecvDump.ino b/hardware/digistump/avr/libraries/DigisparkIRLib/examples/IRrecvDump/IRrecvDump.ino new file mode 100644 index 0000000..da95119 --- /dev/null +++ b/hardware/digistump/avr/libraries/DigisparkIRLib/examples/IRrecvDump/IRrecvDump.ino @@ -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 + +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(); + } +} + diff --git a/hardware/digistump/avr/libraries/DigisparkIRLib/examples/IRsendDemo/IRsendDemo.ino b/hardware/digistump/avr/libraries/DigisparkIRLib/examples/IRsendDemo/IRsendDemo.ino new file mode 100644 index 0000000..607d93a --- /dev/null +++ b/hardware/digistump/avr/libraries/DigisparkIRLib/examples/IRsendDemo/IRsendDemo.ino @@ -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 + +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); + } +} + diff --git a/hardware/digistump/avr/libraries/DigisparkIRLib/examples/IRsendJVC/IRsendJVC.ino b/hardware/digistump/avr/libraries/DigisparkIRLib/examples/IRsendJVC/IRsendJVC.ino new file mode 100644 index 0000000..b9a88e2 --- /dev/null +++ b/hardware/digistump/avr/libraries/DigisparkIRLib/examples/IRsendJVC/IRsendJVC.ino @@ -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 + +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); + } +} + diff --git a/hardware/digistump/avr/libraries/DigisparkIRLib/examples/IRserial_remote/IRserial_remote.ino b/hardware/digistump/avr/libraries/DigisparkIRLib/examples/IRserial_remote/IRserial_remote.ino new file mode 100644 index 0000000..24cc0b3 --- /dev/null +++ b/hardware/digistump/avr/libraries/DigisparkIRLib/examples/IRserial_remote/IRserial_remote.ino @@ -0,0 +1,50 @@ +#include + +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); + } +} diff --git a/hardware/digistump/avr/libraries/DigisparkIRLib/examples/IRserial_remote/IRserial_remote.py b/hardware/digistump/avr/libraries/DigisparkIRLib/examples/IRserial_remote/IRserial_remote.py new file mode 100644 index 0000000..33cb042 --- /dev/null +++ b/hardware/digistump/avr/libraries/DigisparkIRLib/examples/IRserial_remote/IRserial_remote.py @@ -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 + + + diff --git a/hardware/digistump/avr/libraries/DigisparkIRLib/examples/IRserial_remote/POV-Ray/remotebg.pov b/hardware/digistump/avr/libraries/DigisparkIRLib/examples/IRserial_remote/POV-Ray/remotebg.pov new file mode 100644 index 0000000..d964b2f --- /dev/null +++ b/hardware/digistump/avr/libraries/DigisparkIRLib/examples/IRserial_remote/POV-Ray/remotebg.pov @@ -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>} + box{<-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 + } + #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! \ No newline at end of file diff --git a/hardware/digistump/avr/libraries/DigisparkIRLib/examples/IRserial_remote/click.wav b/hardware/digistump/avr/libraries/DigisparkIRLib/examples/IRserial_remote/click.wav new file mode 100644 index 0000000..dbc4c22 Binary files /dev/null and b/hardware/digistump/avr/libraries/DigisparkIRLib/examples/IRserial_remote/click.wav differ diff --git a/hardware/digistump/avr/libraries/DigisparkIRLib/examples/IRserial_remote/remotebg.png b/hardware/digistump/avr/libraries/DigisparkIRLib/examples/IRserial_remote/remotebg.png new file mode 100644 index 0000000..28bc828 Binary files /dev/null and b/hardware/digistump/avr/libraries/DigisparkIRLib/examples/IRserial_remote/remotebg.png differ diff --git a/hardware/digistump/avr/libraries/DigisparkIRLib/examples/IRservo/IRservo.ino b/hardware/digistump/avr/libraries/DigisparkIRLib/examples/IRservo/IRservo.ino new file mode 100644 index 0000000..6c46ebc --- /dev/null +++ b/hardware/digistump/avr/libraries/DigisparkIRLib/examples/IRservo/IRservo.ino @@ -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 +#include +// 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(); + } +} diff --git a/hardware/digistump/avr/libraries/DigisparkIRLib/examples/Samsung36/Samsung36.ino b/hardware/digistump/avr/libraries/DigisparkIRLib/examples/Samsung36/Samsung36.ino new file mode 100644 index 0000000..4bc5bfb --- /dev/null +++ b/hardware/digistump/avr/libraries/DigisparkIRLib/examples/Samsung36/Samsung36.ino @@ -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 +#include + +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_castSAMSUNG36; + 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(); + } +} + diff --git a/hardware/digistump/avr/libraries/RcSeq/Examples/DigiRcSeqZodiac/DigiRcSeqZodiac.ino b/hardware/digistump/avr/libraries/DigisparkRcSeq/Examples/DigiRcSeqZodiac/DigiRcSeqZodiac.ino similarity index 99% rename from hardware/digistump/avr/libraries/RcSeq/Examples/DigiRcSeqZodiac/DigiRcSeqZodiac.ino rename to hardware/digistump/avr/libraries/DigisparkRcSeq/Examples/DigiRcSeqZodiac/DigiRcSeqZodiac.ino index 333fd77..3170281 100644 --- a/hardware/digistump/avr/libraries/RcSeq/Examples/DigiRcSeqZodiac/DigiRcSeqZodiac.ino +++ b/hardware/digistump/avr/libraries/DigisparkRcSeq/Examples/DigiRcSeqZodiac/DigiRcSeqZodiac.ino @@ -19,6 +19,7 @@ IMPORTANT: For this sketch, which is using library: 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. + 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". 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! diff --git a/hardware/digistump/avr/libraries/DigisparkRcSeq/Examples/MultiPosSwitch/MultiPosSwitch.ino b/hardware/digistump/avr/libraries/DigisparkRcSeq/Examples/MultiPosSwitch/MultiPosSwitch.ino new file mode 100644 index 0000000..d70fc92 --- /dev/null +++ b/hardware/digistump/avr/libraries/DigisparkRcSeq/Examples/MultiPosSwitch/MultiPosSwitch.ino @@ -0,0 +1,115 @@ +#include +#include +#include + +/* +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 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: + ==== + 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 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); +} + diff --git a/hardware/digistump/avr/libraries/RcSeq/Examples/OnePropTo5/OnePropTo5.ino b/hardware/digistump/avr/libraries/DigisparkRcSeq/Examples/OnePropTo5/OnePropTo5.ino similarity index 87% rename from hardware/digistump/avr/libraries/RcSeq/Examples/OnePropTo5/OnePropTo5.ino rename to hardware/digistump/avr/libraries/DigisparkRcSeq/Examples/OnePropTo5/OnePropTo5.ino index 648d30c..f5cf501 100644 --- a/hardware/digistump/avr/libraries/RcSeq/Examples/OnePropTo5/OnePropTo5.ino +++ b/hardware/digistump/avr/libraries/DigisparkRcSeq/Examples/OnePropTo5/OnePropTo5.ino @@ -1,12 +1,15 @@ #include #include #include -#include /* +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. 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: ================================================================================================ @@ -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 */ -#define DECLARE_TOGGLE_ACTION(Idx) \ -void ToggleAction##Idx(void) \ -{ \ -static boolean Etat=HIGH; \ - digitalWrite(Idx, Etat); \ - Etat=!Etat; \ +#define DECLARE_TOGGLE_ACTION(Idx) \ +void ToggleAction##Idx(void) \ +{ \ +static uint32_t StartMs=millis(); \ +static boolean Etat=HIGH; \ + \ +/* Since version 2.0 of the 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 */ diff --git a/hardware/digistump/avr/libraries/RcSeq/Examples/RcSeqDemo/RcSeqDemo.ino b/hardware/digistump/avr/libraries/DigisparkRcSeq/Examples/RcSeqDemo/RcSeqDemo.ino similarity index 92% rename from hardware/digistump/avr/libraries/RcSeq/Examples/RcSeqDemo/RcSeqDemo.ino rename to hardware/digistump/avr/libraries/DigisparkRcSeq/Examples/RcSeqDemo/RcSeqDemo.ino index 534e79b..6c4d477 100644 --- a/hardware/digistump/avr/libraries/RcSeq/Examples/RcSeqDemo/RcSeqDemo.ino +++ b/hardware/digistump/avr/libraries/DigisparkRcSeq/Examples/RcSeqDemo/RcSeqDemo.ino @@ -1,4 +1,16 @@ +#include +#include /* Ne pas oublier d'inclure la librairie qui est utilisee par la librairie */ +#include /* Ne pas oublier d'inclure la librairie qui est utilisee par la librairie */ +#include /* Ne pas oublier d'inclure la librairie qui est utilisee par la librairie */ + /* +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. 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) @@ -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) Les 3 exemples sont traites dans ce sketch de demo. */ -#include -#include /* Ne pas oublier d'inclure la librairie qui est utilisee par la librairie */ -#include /* Ne pas oublier d'inclure la librairie qui est utilisee par la librairie */ -#include /* Ne pas oublier d'inclure la librairie qui est utilisee par la librairie */ 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 */ 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); - 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 */ + } } diff --git a/hardware/digistump/avr/libraries/RcSeq/Examples/RcSeqZodiac/RcSeqZodiac.ino b/hardware/digistump/avr/libraries/DigisparkRcSeq/Examples/RcSeqZodiac/RcSeqZodiac.ino similarity index 100% rename from hardware/digistump/avr/libraries/RcSeq/Examples/RcSeqZodiac/RcSeqZodiac.ino rename to hardware/digistump/avr/libraries/DigisparkRcSeq/Examples/RcSeqZodiac/RcSeqZodiac.ino diff --git a/hardware/digistump/avr/libraries/RcSeq/Examples/UneVoieVers8/UneVoieVers8.ino b/hardware/digistump/avr/libraries/DigisparkRcSeq/Examples/UneVoieVers8/UneVoieVers8.ino similarity index 78% rename from hardware/digistump/avr/libraries/RcSeq/Examples/UneVoieVers8/UneVoieVers8.ino rename to hardware/digistump/avr/libraries/DigisparkRcSeq/Examples/UneVoieVers8/UneVoieVers8.ino index 0a93a0a..fb1f983 100644 --- a/hardware/digistump/avr/libraries/RcSeq/Examples/UneVoieVers8/UneVoieVers8.ino +++ b/hardware/digistump/avr/libraries/DigisparkRcSeq/Examples/UneVoieVers8/UneVoieVers8.ino @@ -1,7 +1,15 @@ #include #include /* Ne pas oublier d'inclure la librairie qui est utilisee par la librairie */ #include /* Ne pas oublier d'inclure la librairie qui est utilisee par la librairie */ -#include /* Ne pas oublier d'inclure la librairie qui est utilisee par la librairie */ + +/* +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 ======================== 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() */ -#define DECLARE_ACTION(Idx) \ -void Action##Idx(void) \ -{ \ -static boolean Etat=HIGH; \ - digitalWrite(Idx, Etat); \ - Etat=!Etat; \ +#define DECLARE_ACTION(Idx) \ +void Action##Idx(void) \ +{ \ +static uint32_t DebutMs=millis(); \ +static boolean Etat=HIGH; \ +/* Depuis la version 2.0 de la lib , 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 */ diff --git a/hardware/digistump/avr/libraries/RcSeq/RcSeq.cpp b/hardware/digistump/avr/libraries/DigisparkRcSeq/RcSeq.cpp similarity index 92% rename from hardware/digistump/avr/libraries/RcSeq/RcSeq.cpp rename to hardware/digistump/avr/libraries/DigisparkRcSeq/RcSeq.cpp index 596ad18..9e48b66 100644 --- a/hardware/digistump/avr/libraries/RcSeq/RcSeq.cpp +++ b/hardware/digistump/avr/libraries/DigisparkRcSeq/RcSeq.cpp @@ -11,6 +11,7 @@ 3) : a library mainly based on the library, but with a better pulse generation to limit jitter 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) + -Multi position switch (2 pos switch, 3 pos switch, or more, eg. rotactor) -Keyboard ( assumes Push-Buttons associated Pulse duration are equidistant) -Custom Keyboard (The pulse durations can be defined independently for each Push-Button) 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()). http://p.loussouarn.free.fr - Francais: par RC Navy (2012) + Francais: par RC Navy (2012/2013) ======== 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) @@ -31,6 +32,7 @@ 3) : une librairie majoritairement basee sur la librairie , 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: -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 ( 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) Quelques definitions: @@ -74,14 +76,10 @@ /************************************************************************* MACROS *************************************************************************/ -/* For an easy Library Version Management */ -#define LIB_VERSION 1 -#define LIB_REVISION 0 - #define STR(s) #s #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 */ #define SET_BIT(Value,BitIdx) (Value)|= (1<<(BitIdx)) @@ -92,11 +90,8 @@ #define REFRESH_INTERVAL_MS 20L /* A pulse shall be valid during XXXX_PULSE_CHECK_MS before being taken into account */ -#define STICK_PULSE_CHECK_MS 100L -#define KBD_PULSE_CHECK_MS 10L - -/* Duration between 2 consecutive commands */ -#define INTER_CMD_DURATION_MS 1000L +#define STICK_PULSE_CHECK_MS 150L +#define KBD_PULSE_CHECK_MS 50L /* Free servo Indicator */ #define NO_SEQ_LINE 255 @@ -115,11 +110,18 @@ #define PGM_READ_32(FlashAddr) pgm_read_dword(&(FlashAddr)) /* -STICK TYPE: +STICK TYPE: (dead zone expected at the middle) ========== Pos 0 1 2 3 |---|-|---|--|---|-|---| 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 INACTIVE_AREA_STEP_NBR 1 @@ -156,11 +158,13 @@ typedef struct { }RcCmdSt_t; #endif +#ifdef RC_SEQ_WITH_SOFT_RC_PULSE_OUT_SUPPORT typedef struct { SoftRcPulseOut Motor; 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; }ServoSt_t; +#endif /************************************************************************* GLOBAL VARIABLES *************************************************************************/ @@ -172,11 +176,15 @@ static RcCmdSt_t RcChannel[RC_CMD_MAX_NB]; #endif #ifdef RC_SEQ_WITH_STATIC_MEM_ALLOC_SUPPORT #define AsMember . +#ifdef RC_SEQ_WITH_SOFT_RC_PULSE_OUT_SUPPORT static ServoSt_t Servo[SERVO_MAX_NB]; +#endif static CmdSequenceSt_t CmdSequence[SEQUENCE_MAX_NB]; #else #define AsMember -> +#ifdef RC_SEQ_WITH_SOFT_RC_PULSE_OUT_SUPPORT static ServoSt_t **Servo=NULL; +#endif static CmdSequenceSt_t **CmdSequence=NULL; #endif /************************************************************************* @@ -217,12 +225,12 @@ void RcSeq_Init(void) //======================================================================================================================== uint8_t RcSeq_LibVersion(void) { - return(LIB_VERSION); + return(RC_SEQ_LIB_VERSION); } //======================================================================================================================== uint8_t RcSeq_LibRevision(void) { - return(LIB_REVISION); + return(RC_SEQ_LIB_REVISION); } //======================================================================================================================== char *RcSeq_LibTextVersionRevision(void) @@ -230,6 +238,7 @@ char *RcSeq_LibTextVersionRevision(void) return(LIB_TEXT_VERSION_REVISION); } //======================================================================================================================== +#ifdef RC_SEQ_WITH_SOFT_RC_PULSE_OUT_SUPPORT void RcSeq_DeclareServo(uint8_t Idx, uint8_t DigitalPin) { #ifdef RC_SEQ_WITH_STATIC_MEM_ALLOC_SUPPORT @@ -250,6 +259,7 @@ void RcSeq_DeclareServo(uint8_t Idx, uint8_t DigitalPin) } #endif } +#endif //======================================================================================================================== #ifdef RC_SEQ_WITH_SOFT_RC_PULSE_IN_SUPPORT void RcSeq_DeclareSignal(uint8_t Idx, uint8_t DigitalPin) @@ -298,7 +308,8 @@ uint32_t StartMinMs[SERVO_MAX_NB]; #else LoadSequenceOrShortAction(CmdIdx,Pos,(void*)Table, SequenceLength); #endif - + +#ifdef RC_SEQ_WITH_SOFT_RC_PULSE_OUT_SUPPORT /* Get initial pulse width for each Servo */ for(Idx=0;Idx=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 { @@ -416,7 +426,7 @@ uint32_t RcPulseWidthUs; } #endif NowMs=millis(); - if((NowMs - StartChronoInterPulseMs) >= 20L) + if((NowMs - StartChronoInterPulseMs) >= 20UL) { /* We arrive here every 20 ms */ /* Asynchronous Servo Sequence management */ @@ -448,6 +458,7 @@ uint32_t RcPulseWidthUs; continue; } #endif +#ifdef RC_SEQ_WITH_SOFT_RC_PULSE_OUT_SUPPORT if(Servo[ServoIdx] AsMember RefreshNb && SeqLine!=Servo[ServoIdx] AsMember SeqLineInProgress) { continue; @@ -484,9 +495,12 @@ uint32_t RcPulseWidthUs; } } } +#endif } } +#ifdef RC_SEQ_WITH_SOFT_RC_PULSE_OUT_SUPPORT SoftRcPulseOut::refresh(1); /* Force Refresh */ +#endif StartChronoInterPulseMs=millis(); } } @@ -535,9 +549,9 @@ uint16_t PulseMinUs,PulseMaxUs; { switch(RcChannel[ChIdx].Type) { - case RC_CMD_STICK: /* No break: normal */ - case RC_CMD_KEYBOARD: - if(Idx<(RcChannel[ChIdx].PosNb/2)) + case RC_CMD_STICK: /* No break: normal */ + case RC_CMD_MULTI_POS_SW: + 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); PulseMaxUs=RcChannel[ChIdx].PulseMinUs+KEY_MAX_VAL(Idx,RcChannel[ChIdx].StepUs); @@ -548,11 +562,11 @@ uint16_t PulseMinUs,PulseMaxUs; PulseMaxUs=RcChannel[ChIdx].PulseMaxUs-KEY_MIN_VAL(RcChannel[ChIdx].PosNb-1-Idx,RcChannel[ChIdx].StepUs); } break; - - case RC_CMD_CUSTOM: - PulseMinUs=(uint16_t)PGM_READ_16(RcChannel[ChIdx].KeyMap[Idx].Min); - PulseMaxUs=(uint16_t)PGM_READ_16(RcChannel[ChIdx].KeyMap[Idx].Max); - break; + + case RC_CMD_CUSTOM: + PulseMinUs=(uint16_t)PGM_READ_16(RcChannel[ChIdx].KeyMap[Idx].Min); + PulseMaxUs=(uint16_t)PGM_READ_16(RcChannel[ChIdx].KeyMap[Idx].Max); + break; } if((PulseWidthUs>=PulseMinUs) && (PulseWidthUs<=PulseMaxUs)) { diff --git a/hardware/digistump/avr/libraries/RcSeq/RcSeq.h b/hardware/digistump/avr/libraries/DigisparkRcSeq/RcSeq.h similarity index 86% rename from hardware/digistump/avr/libraries/RcSeq/RcSeq.h rename to hardware/digistump/avr/libraries/DigisparkRcSeq/RcSeq.h index 93dbe8d..7beb9ce 100644 --- a/hardware/digistump/avr/libraries/RcSeq/RcSeq.h +++ b/hardware/digistump/avr/libraries/DigisparkRcSeq/RcSeq.h @@ -2,7 +2,7 @@ #define RC_SEQ_H /* - English: by RC Navy (2012) + English: by RC Navy (2012/2013) ======= 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) @@ -13,6 +13,7 @@ 3) : a library mainly based on the library, but with a better pulse generation to limit jitter 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) + -Multi position switch (2 pos switch, 3 pos switch, or more, eg. rotactor) -Keyboard ( assumes Push-Buttons associated Pulse duration are equidistant) -Custom Keyboard (The pulse durations can be defined independently for each Push-Button) 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()). http://p.loussouarn.free.fr - Francais: par RC Navy (2012) + Francais: par RC Navy (2012/2013) ======== 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) @@ -33,6 +34,7 @@ 3) : une librairie majoritairement basee sur la librairie , 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: -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 ( 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) Quelques definitions: @@ -45,15 +47,20 @@ /**********************************************/ /* RCSEQ LIBRARY CONFIGURATION */ /**********************************************/ -//#define RC_SEQ_WITH_SOFT_RC_PULSE_IN_SUPPORT /* Comment this line if you use 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_IN_SUPPORT /* Comment this line if you use library in your sketch */ +//#define RC_SEQ_WITH_SOFT_RC_PULSE_OUT_SUPPORT /* Uncomment this if you use 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 /!\ */ /**********************************************/ -#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 #include @@ -64,7 +71,11 @@ #ifndef RC_SEQ_WITH_SHORT_ACTION_SUPPORT #warning RC_SEQ_WITH_SHORT_ACTION_SUPPORT disabled: no short action possible!!! #endif +#ifdef RC_SEQ_WITH_SOFT_RC_PULSE_OUT_SUPPORT #include +#else +#warning RC_SEQ_WITH_SOFT_RC_PULSE_OUT_SUPPORT disabled: no Servo/ESC command possible!!! +#endif #if defined(ARDUINO) && ARDUINO >= 100 #include "Arduino.h" @@ -114,7 +125,7 @@ typedef struct { /* 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)}, -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_CUSTOM_KEYBOARD(KeyMap) KeyMap, TABLE_ITEM_NBR(KeyMap) @@ -125,13 +136,16 @@ void RcSeq_Init(void); uint8_t RcSeq_LibVersion(void); uint8_t RcSeq_LibRevision(void); char *RcSeq_LibTextVersionRevision(void); +#ifdef RC_SEQ_WITH_SOFT_RC_PULSE_OUT_SUPPORT void RcSeq_DeclareServo(uint8_t Idx, uint8_t DigitalPin); +#endif #ifdef RC_SEQ_WITH_SOFT_RC_PULSE_IN_SUPPORT 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_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_DeclareKeyboard(ChIdx, PulseMinUs, PulseMaxUs, KeyNb) RcSeq_DeclareKeyboardOrStickOrCustom(ChIdx, RC_CMD_KEYBOARD, PulseMinUs, PulseMaxUs, NULL, KeyNb) +#define RcSeq_DeclareStick(ChIdx, PulseMinUs, PulseMaxUs, PosNb) RcSeq_DeclareKeyboardOrStickOrCustom(ChIdx, RC_CMD_STICK, PulseMinUs, PulseMaxUs, NULL, PosNb) +#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 void RcSeq_DeclareCommandAndShortAction(uint8_t CmdIdx,uint8_t TypeCmd,void(*ShortAction)(void)); #endif @@ -161,6 +175,7 @@ void RcSeq_Refresh(void); #define RcSeq_DeclareManche RcSeq_DeclareStick #define RcSeq_DeclareClavier RcSeq_DeclareKeyboard #define RcSeq_DeclareClavierMaison RcSeq_DeclareCustomKeyboard +#define RcSeq_DeclareInterMultiPos RcSeq_DeclareMultiPosSwitch #define RcSeq_DeclareCommandeEtActionCourte RcSeq_DeclareCommandAndShortAction #endif #define RcSeq_DeclareCommandeEtSequence RcSeq_DeclareCommandAndSequence diff --git a/hardware/digistump/avr/libraries/RcSeq/keywords.txt b/hardware/digistump/avr/libraries/DigisparkRcSeq/keywords.txt similarity index 95% rename from hardware/digistump/avr/libraries/RcSeq/keywords.txt rename to hardware/digistump/avr/libraries/DigisparkRcSeq/keywords.txt index 2a3b465..759c4a0 100644 --- a/hardware/digistump/avr/libraries/RcSeq/keywords.txt +++ b/hardware/digistump/avr/libraries/DigisparkRcSeq/keywords.txt @@ -22,6 +22,8 @@ RcSeq_DeclareManche KEYWORD2 RcSeq_DeclareServo KEYWORD2 RcSeq_DeclareCustomKeyboard KEYWORD2 RcSeq_DeclareClavierMaison KEYWORD2 +RcSeq_DeclareMultiPosSwitch KEYWORD2 +RcSeq_DeclareInterMultiPos KEYWORD2 RcSeq_DeclareCommandAndSequence KEYWORD2 RcSeq_DeclareCommandeEtSequence KEYWORD2 RcSeq_DeclareCommandAndShortAction KEYWORD2 diff --git a/hardware/digistump/avr/libraries/SimpleServo/.DS_Store b/hardware/digistump/avr/libraries/DigisparkSimpleServo/.DS_Store similarity index 100% rename from hardware/digistump/avr/libraries/SimpleServo/.DS_Store rename to hardware/digistump/avr/libraries/DigisparkSimpleServo/.DS_Store diff --git a/hardware/digistump/avr/libraries/SimpleServo/README.txt b/hardware/digistump/avr/libraries/DigisparkSimpleServo/README.txt similarity index 100% rename from hardware/digistump/avr/libraries/SimpleServo/README.txt rename to hardware/digistump/avr/libraries/DigisparkSimpleServo/README.txt diff --git a/hardware/digistump/avr/libraries/SimpleServo/SimpleServo.cpp b/hardware/digistump/avr/libraries/DigisparkSimpleServo/SimpleServo.cpp similarity index 100% rename from hardware/digistump/avr/libraries/SimpleServo/SimpleServo.cpp rename to hardware/digistump/avr/libraries/DigisparkSimpleServo/SimpleServo.cpp diff --git a/hardware/digistump/avr/libraries/SimpleServo/SimpleServo.h b/hardware/digistump/avr/libraries/DigisparkSimpleServo/SimpleServo.h similarity index 100% rename from hardware/digistump/avr/libraries/SimpleServo/SimpleServo.h rename to hardware/digistump/avr/libraries/DigisparkSimpleServo/SimpleServo.h diff --git a/hardware/digistump/avr/libraries/SimpleServo/examples/.DS_Store b/hardware/digistump/avr/libraries/DigisparkSimpleServo/examples/.DS_Store similarity index 100% rename from hardware/digistump/avr/libraries/SimpleServo/examples/.DS_Store rename to hardware/digistump/avr/libraries/DigisparkSimpleServo/examples/.DS_Store diff --git a/hardware/digistump/avr/libraries/SimpleServo/keywords.txt b/hardware/digistump/avr/libraries/DigisparkSimpleServo/keywords.txt similarity index 100% rename from hardware/digistump/avr/libraries/SimpleServo/keywords.txt rename to hardware/digistump/avr/libraries/DigisparkSimpleServo/keywords.txt diff --git a/hardware/digistump/avr/libraries/SoftRcPulseIn/SoftRcPulseIn.cpp b/hardware/digistump/avr/libraries/DigisparkSoftRcPulseIn/SoftRcPulseIn.cpp similarity index 95% rename from hardware/digistump/avr/libraries/SoftRcPulseIn/SoftRcPulseIn.cpp rename to hardware/digistump/avr/libraries/DigisparkSoftRcPulseIn/SoftRcPulseIn.cpp index 70a4d12..7b6c00b 100644 --- a/hardware/digistump/avr/libraries/SoftRcPulseIn/SoftRcPulseIn.cpp +++ b/hardware/digistump/avr/libraries/DigisparkSoftRcPulseIn/SoftRcPulseIn.cpp @@ -37,6 +37,7 @@ uint8_t Ret=0; next = first; first = this; pinMode(_Pin,INPUT); + digitalWrite(_Pin, HIGH); _VirtualPortIdx=TinyPinChange_RegisterIsr(_Pin,SoftRcPulseIn::SoftRcPulseInInterrupt); if(_VirtualPortIdx>=0) { @@ -92,7 +93,7 @@ SoftRcPulseIn *RcPulseIn; 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)) { diff --git a/hardware/digistump/avr/libraries/SoftRcPulseIn/SoftRcPulseIn.h b/hardware/digistump/avr/libraries/DigisparkSoftRcPulseIn/SoftRcPulseIn.h similarity index 100% rename from hardware/digistump/avr/libraries/SoftRcPulseIn/SoftRcPulseIn.h rename to hardware/digistump/avr/libraries/DigisparkSoftRcPulseIn/SoftRcPulseIn.h diff --git a/hardware/digistump/avr/libraries/DigisparkSoftRcPulseIn/examples/SoftRcPulseInDebug/SoftRcPulseInDebug.ino b/hardware/digistump/avr/libraries/DigisparkSoftRcPulseIn/examples/SoftRcPulseInDebug/SoftRcPulseInDebug.ino new file mode 100644 index 0000000..6a467c0 --- /dev/null +++ b/hardware/digistump/avr/libraries/DigisparkSoftRcPulseIn/examples/SoftRcPulseInDebug/SoftRcPulseInDebug.ino @@ -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 +#include +#include + +#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) + } +} + + diff --git a/hardware/digistump/avr/libraries/SoftRcPulseIn/examples/SoftRcPulseInDemo/SoftRcPulseInDemo.ino b/hardware/digistump/avr/libraries/DigisparkSoftRcPulseIn/examples/SoftRcPulseInDemo/SoftRcPulseInDemo.ino similarity index 100% rename from hardware/digistump/avr/libraries/SoftRcPulseIn/examples/SoftRcPulseInDemo/SoftRcPulseInDemo.ino rename to hardware/digistump/avr/libraries/DigisparkSoftRcPulseIn/examples/SoftRcPulseInDemo/SoftRcPulseInDemo.ino diff --git a/hardware/digistump/avr/libraries/SoftRcPulseIn/examples/SoftRcPulseInOutDemo/SoftRcPulseInOutDemo.ino b/hardware/digistump/avr/libraries/DigisparkSoftRcPulseIn/examples/SoftRcPulseInOutDemo/SoftRcPulseInOutDemo.ino similarity index 100% rename from hardware/digistump/avr/libraries/SoftRcPulseIn/examples/SoftRcPulseInOutDemo/SoftRcPulseInOutDemo.ino rename to hardware/digistump/avr/libraries/DigisparkSoftRcPulseIn/examples/SoftRcPulseInOutDemo/SoftRcPulseInOutDemo.ino diff --git a/hardware/digistump/avr/libraries/SoftRcPulseIn/keywords.txt b/hardware/digistump/avr/libraries/DigisparkSoftRcPulseIn/keywords.txt similarity index 100% rename from hardware/digistump/avr/libraries/SoftRcPulseIn/keywords.txt rename to hardware/digistump/avr/libraries/DigisparkSoftRcPulseIn/keywords.txt diff --git a/hardware/digistump/avr/libraries/SoftRcPulseOut/SoftRcPulseOut.cpp b/hardware/digistump/avr/libraries/DigisparkSoftRcPulseOut/SoftRcPulseOut.cpp similarity index 100% rename from hardware/digistump/avr/libraries/SoftRcPulseOut/SoftRcPulseOut.cpp rename to hardware/digistump/avr/libraries/DigisparkSoftRcPulseOut/SoftRcPulseOut.cpp diff --git a/hardware/digistump/avr/libraries/SoftRcPulseOut/SoftRcPulseOut.h b/hardware/digistump/avr/libraries/DigisparkSoftRcPulseOut/SoftRcPulseOut.h similarity index 100% rename from hardware/digistump/avr/libraries/SoftRcPulseOut/SoftRcPulseOut.h rename to hardware/digistump/avr/libraries/DigisparkSoftRcPulseOut/SoftRcPulseOut.h diff --git a/hardware/digistump/avr/libraries/SoftRcPulseOut/examples/Knob/Knob.ino b/hardware/digistump/avr/libraries/DigisparkSoftRcPulseOut/examples/Knob/Knob.ino similarity index 100% rename from hardware/digistump/avr/libraries/SoftRcPulseOut/examples/Knob/Knob.ino rename to hardware/digistump/avr/libraries/DigisparkSoftRcPulseOut/examples/Knob/Knob.ino diff --git a/hardware/digistump/avr/libraries/SoftRcPulseOut/examples/SerialServo/SerialServo.ino b/hardware/digistump/avr/libraries/DigisparkSoftRcPulseOut/examples/SerialServo/SerialServo.ino similarity index 100% rename from hardware/digistump/avr/libraries/SoftRcPulseOut/examples/SerialServo/SerialServo.ino rename to hardware/digistump/avr/libraries/DigisparkSoftRcPulseOut/examples/SerialServo/SerialServo.ino diff --git a/hardware/digistump/avr/libraries/SoftRcPulseOut/examples/SoftRcPulseInOutDemo/SoftRcPulseInOutDemo.ino b/hardware/digistump/avr/libraries/DigisparkSoftRcPulseOut/examples/SoftRcPulseInOutDemo/SoftRcPulseInOutDemo.ino similarity index 100% rename from hardware/digistump/avr/libraries/SoftRcPulseOut/examples/SoftRcPulseInOutDemo/SoftRcPulseInOutDemo.ino rename to hardware/digistump/avr/libraries/DigisparkSoftRcPulseOut/examples/SoftRcPulseInOutDemo/SoftRcPulseInOutDemo.ino diff --git a/hardware/digistump/avr/libraries/SoftRcPulseOut/examples/Sweep/Sweep.ino b/hardware/digistump/avr/libraries/DigisparkSoftRcPulseOut/examples/Sweep/Sweep.ino similarity index 100% rename from hardware/digistump/avr/libraries/SoftRcPulseOut/examples/Sweep/Sweep.ino rename to hardware/digistump/avr/libraries/DigisparkSoftRcPulseOut/examples/Sweep/Sweep.ino diff --git a/hardware/digistump/avr/libraries/SoftRcPulseOut/examples/Usb2Servos/Usb2Servos.ino b/hardware/digistump/avr/libraries/DigisparkSoftRcPulseOut/examples/Usb2Servos/Usb2Servos.ino similarity index 100% rename from hardware/digistump/avr/libraries/SoftRcPulseOut/examples/Usb2Servos/Usb2Servos.ino rename to hardware/digistump/avr/libraries/DigisparkSoftRcPulseOut/examples/Usb2Servos/Usb2Servos.ino diff --git a/hardware/digistump/avr/libraries/SoftRcPulseOut/examples/knob_moyennee/knob_moyennee.ino b/hardware/digistump/avr/libraries/DigisparkSoftRcPulseOut/examples/knob_moyennee/knob_moyennee.ino similarity index 100% rename from hardware/digistump/avr/libraries/SoftRcPulseOut/examples/knob_moyennee/knob_moyennee.ino rename to hardware/digistump/avr/libraries/DigisparkSoftRcPulseOut/examples/knob_moyennee/knob_moyennee.ino diff --git a/hardware/digistump/avr/libraries/SoftRcPulseOut/keywords.txt b/hardware/digistump/avr/libraries/DigisparkSoftRcPulseOut/keywords.txt similarity index 100% rename from hardware/digistump/avr/libraries/SoftRcPulseOut/keywords.txt rename to hardware/digistump/avr/libraries/DigisparkSoftRcPulseOut/keywords.txt diff --git a/hardware/digistump/avr/libraries/SoftSerial/SoftSerial.cpp b/hardware/digistump/avr/libraries/DigisparkSoftSerial/SoftSerial.cpp similarity index 100% rename from hardware/digistump/avr/libraries/SoftSerial/SoftSerial.cpp rename to hardware/digistump/avr/libraries/DigisparkSoftSerial/SoftSerial.cpp diff --git a/hardware/digistump/avr/libraries/SoftSerial/SoftSerial.h b/hardware/digistump/avr/libraries/DigisparkSoftSerial/SoftSerial.h similarity index 100% rename from hardware/digistump/avr/libraries/SoftSerial/SoftSerial.h rename to hardware/digistump/avr/libraries/DigisparkSoftSerial/SoftSerial.h diff --git a/hardware/digistump/avr/libraries/SoftSerial/examples/Digi_1io_SerialDbg/Digi_1io_SerialDbg.ino b/hardware/digistump/avr/libraries/DigisparkSoftSerial/examples/Digi_1io_SerialDbg/Digi_1io_SerialDbg.ino similarity index 100% rename from hardware/digistump/avr/libraries/SoftSerial/examples/Digi_1io_SerialDbg/Digi_1io_SerialDbg.ino rename to hardware/digistump/avr/libraries/DigisparkSoftSerial/examples/Digi_1io_SerialDbg/Digi_1io_SerialDbg.ino diff --git a/hardware/digistump/avr/libraries/SoftSerial/examples/SoftSerialExample/SoftSerialExample.ino b/hardware/digistump/avr/libraries/DigisparkSoftSerial/examples/SoftSerialExample/SoftSerialExample.ino similarity index 100% rename from hardware/digistump/avr/libraries/SoftSerial/examples/SoftSerialExample/SoftSerialExample.ino rename to hardware/digistump/avr/libraries/DigisparkSoftSerial/examples/SoftSerialExample/SoftSerialExample.ino diff --git a/hardware/digistump/avr/libraries/SoftSerial/examples/TwoPortReceive/TwoPortReceive.ino b/hardware/digistump/avr/libraries/DigisparkSoftSerial/examples/TwoPortReceive/TwoPortReceive.ino similarity index 100% rename from hardware/digistump/avr/libraries/SoftSerial/examples/TwoPortReceive/TwoPortReceive.ino rename to hardware/digistump/avr/libraries/DigisparkSoftSerial/examples/TwoPortReceive/TwoPortReceive.ino diff --git a/hardware/digistump/avr/libraries/SoftSerial/keywords.txt b/hardware/digistump/avr/libraries/DigisparkSoftSerial/keywords.txt similarity index 100% rename from hardware/digistump/avr/libraries/SoftSerial/keywords.txt rename to hardware/digistump/avr/libraries/DigisparkSoftSerial/keywords.txt diff --git a/hardware/digistump/avr/libraries/DigisparkTinyPinChange/TinyPinChange.cpp b/hardware/digistump/avr/libraries/DigisparkTinyPinChange/TinyPinChange.cpp new file mode 100644 index 0000000..f173355 --- /dev/null +++ b/hardware/digistump/avr/libraries/DigisparkTinyPinChange/TinyPinChange.cpp @@ -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 +#include + +/************************************************************************* + 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); +} diff --git a/hardware/digistump/avr/libraries/DigisparkTinyPinChange/TinyPinChange.h b/hardware/digistump/avr/libraries/DigisparkTinyPinChange/TinyPinChange.h new file mode 100644 index 0000000..d2aef47 --- /dev/null +++ b/hardware/digistump/avr/libraries/DigisparkTinyPinChange/TinyPinChange.h @@ -0,0 +1,116 @@ +#ifndef TINY_PIN_CHANGE_H +#define TINY_PIN_CHANGE_H 1 + +/* +* , 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 + +#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 diff --git a/hardware/digistump/avr/libraries/TinyPinChange/examples/TinyPinChangeDemo/TinyPinChangeDemo.ino b/hardware/digistump/avr/libraries/DigisparkTinyPinChange/examples/Edge/Edge.ino similarity index 78% rename from hardware/digistump/avr/libraries/TinyPinChange/examples/TinyPinChangeDemo/TinyPinChangeDemo.ino rename to hardware/digistump/avr/libraries/DigisparkTinyPinChange/examples/Edge/Edge.ino index ee55a59..dbc78c3 100644 --- a/hardware/digistump/avr/libraries/TinyPinChange/examples/TinyPinChangeDemo/TinyPinChangeDemo.ino +++ b/hardware/digistump/avr/libraries/DigisparkTinyPinChange/examples/Edge/Edge.ino @@ -4,7 +4,7 @@ | |__| | | / \_| | . \ | | / / \ \ | | | | \ \ / / | _ / | | _ | |\ \| | | |__| | | | | | \ ' / | | \ \ | \__/ | | | \ ' | | __ | \ \/ / | | - |_| \_\ \____/ |_| \__| |_| |_| \__/ |_| 2013 + |_| \_\ \____/ |_| \__| |_| |_| \__/ |_| 2013/2014 http://p.loussouarn.free.fr @@ -15,7 +15,7 @@ ******************************************************* This sketch demonstrates how to use library. -It counts all the transitions on 2 different pins. +It counts all the transitions (both edges) on 2 different pins. /!\CAUTION/!\: as 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. @@ -58,8 +58,8 @@ To display the sketch results on a PC (in a Terminal): #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 */ +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) */ @@ -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) */ - VirtualPortNb=TinyPinChange_RegisterIsr(FIRST_INPUT, InterruptFunctionToCall); - VirtualPortNb_=TinyPinChange_RegisterIsr(SECOND_INPUT, InterruptFunctionToCall); + 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 ***")); + MySerial.println(F("\n*** Tiny PinChange Demo (Rising AND Falling edges) ***")); MySerial.print(F("Pin "));MySerial.print((int)FIRST_INPUT); MySerial.print(F(" is part of virtual port "));MySerial.println((int)VirtualPortNb); @@ -88,7 +88,8 @@ void setup() 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 is also designed for UNO, MEGA and ATtiny84 ;-)")); + MySerial.println(F("Remember 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); @@ -98,14 +99,12 @@ void setup() /* Function called in interruption in case of change on pins */ void InterruptFunctionToCall(void) { -uint8_t PortChange; - - PortChange = TinyPinChange_GetPinEvent(VirtualPortNb); - if(PortChange & TinyPinChange_PinToMsk(FIRST_INPUT)) /* Check FIRST_INPUT has changed */ + if(TinyPinChange_Edge(VirtualPortNb, FIRST_INPUT)) /* Check FIRST_INPUT has changed (falling or rising edge) */ { 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 */ } @@ -113,17 +112,17 @@ uint8_t PortChange; void loop() { -static boolean State=HIGH, DisplayEnabled=false; -static uint32_t LedStartMs=millis(), DisplayStartMs=millis(); +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) + if(millis() - LedStartMs >= 500) { - LedStartMs=millis(); + LedStartMs = millis(); 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 */ @@ -132,19 +131,19 @@ uint16_t LocalSecondInputChangeCount; switch(MySerial.read()) { case '0': - DisplayEnabled=false; + DisplayEnabled = false; break; case '1': - DisplayEnabled=true; + DisplayEnabled = true; break; } } /* 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 */ LocalFirstInputChangeCount = FirstInputChangeCount; LocalSecondInputChangeCount = SecondInputChangeCount; diff --git a/hardware/digistump/avr/libraries/DigisparkTinyPinChange/examples/FallingEdge/FallingEdge.ino b/hardware/digistump/avr/libraries/DigisparkTinyPinChange/examples/FallingEdge/FallingEdge.ino new file mode 100644 index 0000000..3ff2f3a --- /dev/null +++ b/hardware/digistump/avr/libraries/DigisparkTinyPinChange/examples/FallingEdge/FallingEdge.ino @@ -0,0 +1,158 @@ +/* + _____ ____ __ _ ____ _ _ _ _ + | __ \ / __ \ | \ | | / __ \ | | | | | | | | + | |__| | | / \_| | . \ | | / / \ \ | | | | \ \ / / + | _ / | | _ | |\ \| | | |__| | | | | | \ ' / + | | \ \ | \__/ | | | \ ' | | __ | \ \/ / | | + |_| \_\ \____/ |_| \__| |_| |_| \__/ |_| 2013/2014 + + http://p.loussouarn.free.fr + + ******************************************************* + * library Demo * + * with debugging capabilities using * + * object as single wire serial interface * + ******************************************************* + +This sketch demonstrates how to use library. +It counts all the FALLING edges on 2 different pins. +/!\CAUTION/!\: as 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 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 +#include + +#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 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(); + } + +} + diff --git a/hardware/digistump/avr/libraries/DigisparkTinyPinChange/examples/RisingEdge/RisingEdge.ino b/hardware/digistump/avr/libraries/DigisparkTinyPinChange/examples/RisingEdge/RisingEdge.ino new file mode 100644 index 0000000..897e532 --- /dev/null +++ b/hardware/digistump/avr/libraries/DigisparkTinyPinChange/examples/RisingEdge/RisingEdge.ino @@ -0,0 +1,158 @@ +/* + _____ ____ __ _ ____ _ _ _ _ + | __ \ / __ \ | \ | | / __ \ | | | | | | | | + | |__| | | / \_| | . \ | | / / \ \ | | | | \ \ / / + | _ / | | _ | |\ \| | | |__| | | | | | \ ' / + | | \ \ | \__/ | | | \ ' | | __ | \ \/ / | | + |_| \_\ \____/ |_| \__| |_| |_| \__/ |_| 2013/2014 + + http://p.loussouarn.free.fr + + ******************************************************* + * library Demo * + * with debugging capabilities using * + * object as single wire serial interface * + ******************************************************* + +This sketch demonstrates how to use library. +It counts all the RISING edges on 2 different pins. +/!\CAUTION/!\: as 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 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 +#include + +#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 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(); + } + +} + diff --git a/hardware/digistump/avr/libraries/TinyPinChange/keywords.txt b/hardware/digistump/avr/libraries/DigisparkTinyPinChange/keywords.txt similarity index 76% rename from hardware/digistump/avr/libraries/TinyPinChange/keywords.txt rename to hardware/digistump/avr/libraries/DigisparkTinyPinChange/keywords.txt index 0f006bc..e230510 100644 --- a/hardware/digistump/avr/libraries/TinyPinChange/keywords.txt +++ b/hardware/digistump/avr/libraries/DigisparkTinyPinChange/keywords.txt @@ -17,12 +17,18 @@ TinyPinChange_EnablePin KEYWORD2 TinyPinChange_ActiveBroche KEYWORD2 TinyPinChange_DisablePin KEYWORD2 TinyPinChange_DesactiveBroche KEYWORD2 -TinyPinChange_GetPinEvent KEYWORD2 +TinyPinChange_GetPortEvent KEYWORD2 TinyPinChange_RetourneEvenemenPort KEYWORD2 -TinyPinChange_GetPinCurSt KEYWORD2 +TinyPinChange_GetCurPortSt KEYWORD2 TinyPinChange_RetourneEtatCourantPort KEYWORD2 TinyPinChange_PinToMsk KEYWORD2 TinyPinChange_MasqueDeBroche KEYWORD2 +TinyPinChange_Edge KEYWORD2 +TinyPinChange_Front KEYWORD2 +TinyPinChange_RisingEdge KEYWORD2 +TinyPinChange_FrontMontant KEYWORD2 +TinyPinChange_FallingEdge KEYWORD2 +TinyPinChange_FrontDescendant KEYWORD2 ####################################### # Constants (LITERAL1) diff --git a/hardware/digistump/avr/libraries/TinySoftPwm/TinySoftPwm.cpp b/hardware/digistump/avr/libraries/DigisparkTinySoftPwm/TinySoftPwm.cpp similarity index 100% rename from hardware/digistump/avr/libraries/TinySoftPwm/TinySoftPwm.cpp rename to hardware/digistump/avr/libraries/DigisparkTinySoftPwm/TinySoftPwm.cpp diff --git a/hardware/digistump/avr/libraries/TinySoftPwm/TinySoftPwm.h b/hardware/digistump/avr/libraries/DigisparkTinySoftPwm/TinySoftPwm.h similarity index 97% rename from hardware/digistump/avr/libraries/TinySoftPwm/TinySoftPwm.h rename to hardware/digistump/avr/libraries/DigisparkTinySoftPwm/TinySoftPwm.h index c163146..448286a 100644 --- a/hardware/digistump/avr/libraries/TinySoftPwm/TinySoftPwm.h +++ b/hardware/digistump/avr/libraries/DigisparkTinySoftPwm/TinySoftPwm.h @@ -20,12 +20,12 @@ /* Define here the PIN to use with Tiny Soft PWM */ /* 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_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_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 diff --git a/hardware/digistump/avr/libraries/TinySoftPwm/examples/TinySoftPwmDemo/TinySoftPwmDemo.ino b/hardware/digistump/avr/libraries/DigisparkTinySoftPwm/examples/TinySoftPwmDemo/TinySoftPwmDemo.ino similarity index 100% rename from hardware/digistump/avr/libraries/TinySoftPwm/examples/TinySoftPwmDemo/TinySoftPwmDemo.ino rename to hardware/digistump/avr/libraries/DigisparkTinySoftPwm/examples/TinySoftPwmDemo/TinySoftPwmDemo.ino diff --git a/hardware/digistump/avr/libraries/TinySoftPwm/keywords.txt b/hardware/digistump/avr/libraries/DigisparkTinySoftPwm/keywords.txt similarity index 100% rename from hardware/digistump/avr/libraries/TinySoftPwm/keywords.txt rename to hardware/digistump/avr/libraries/DigisparkTinySoftPwm/keywords.txt diff --git a/hardware/digistump/avr/libraries/TinyPinChange/TinyPinChange.cpp b/hardware/digistump/avr/libraries/TinyPinChange/TinyPinChange.cpp deleted file mode 100644 index 43b2cd9..0000000 --- a/hardware/digistump/avr/libraries/TinyPinChange/TinyPinChange.cpp +++ /dev/null @@ -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 -#include - -/************************************************************************* - 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, 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 - -#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