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