diff --git a/TVB/TVB.pde b/TVB/TVB.pde
new file mode 100644
index 0000000..f221ec9
--- /dev/null
+++ b/TVB/TVB.pde
@@ -0,0 +1,455 @@
+/*
+TV-B-Gone for Arduino version 1.2, Oct 23 2010
+Ported to Arduino by Ken Shirriff=
+http://www.arcfn.com/2009/12/tv-b-gone-for-arduino.html
+
+The hardware for this project uses an Arduino:
+ Connect an IR LED to pin 3 (RLED).
+ Connect a visible LED to pin 13 (or use builtin LED in some Arduinos).
+ Connect a pushbutton between pin 2 (TRIGGER) and ground.
+ Pin 5 (REGIONSWITCH) is floating for North America, or wired to ground for Europe.
+
+The original code is:
+TV-B-Gone Firmware version 1.2
+ for use with ATtiny85v and v1.2 hardware
+ (c) Mitch Altman + Limor Fried 2009
+ Last edits, August 16 2009
+
+
+ I added universality for EU or NA,
+ and Sleep mode to Ken's Arduino port
+ -- Mitch Altman 18-Oct-2010
+ Thanks to ka1kjz for the code for adding Sleep
+
+
+
+ With some code from:
+ Kevin Timmerman & Damien Good 7-Dec-07
+
+ Distributed under Creative Commons 2.5 -- Attib & Share Alike
+
+ */
+
+#include "main.h"
+#include
+
+void xmitCodeElement(uint16_t ontime, uint16_t offtime, uint8_t PWM_code );
+void quickflashLEDx( uint8_t x );
+void delay_ten_us(uint16_t us);
+void quickflashLED( void );
+uint8_t read_bits(uint8_t count);
+
+#define putstring_nl(s) Serial.println(s)
+#define putstring(s) Serial.print(s)
+#define putnum_ud(n) Serial.print(n, DEC)
+#define putnum_uh(n) Serial.print(n, HEX)
+
+/*
+This project transmits a bunch of TV POWER codes, one right after the other,
+ with a pause in between each. (To have a visible indication that it is
+ transmitting, it also pulses a visible LED once each time a POWER code is
+ transmitted.) That is all TV-B-Gone does. The tricky part of TV-B-Gone
+ was collecting all of the POWER codes, and getting rid of the duplicates and
+ near-duplicates (because if there is a duplicate, then one POWER code will
+ turn a TV off, and the duplicate will turn it on again (which we certainly
+ do not want). I have compiled the most popular codes with the
+ duplicates eliminated, both for North America (which is the same as Asia, as
+ far as POWER codes are concerned -- even though much of Asia USES PAL video)
+ and for Europe (which works for Australia, New Zealand, the Middle East, and
+ other parts of the world that use PAL video).
+
+ Before creating a TV-B-Gone Kit, I originally started this project by hacking
+ the MiniPOV kit. This presents a limitation, based on the size of
+ the Atmel ATtiny2313 internal flash memory, which is 2KB. With 2KB we can only
+ fit about 7 POWER codes into the firmware's database of POWER codes. However,
+ the more codes the better! Which is why we chose the ATtiny85 for the
+ TV-B-Gone Kit.
+
+ This version of the firmware has the most popular 100+ POWER codes for
+ North America and 100+ POWER codes for Europe. You can select which region
+ to use by soldering a 10K pulldown resistor.
+ */
+
+
+/*
+This project is a good example of how to use the AVR chip timers.
+ */
+
+extern PGM_P *NApowerCodes[] PROGMEM;
+extern PGM_P *EUpowerCodes[] PROGMEM;
+extern uint8_t num_NAcodes, num_EUcodes;
+
+/* This function is the 'workhorse' of transmitting IR codes.
+ Given the on and off times, it turns on the PWM output on and off
+ to generate one 'pair' from a long code. Each code has ~50 pairs! */
+void xmitCodeElement(uint16_t ontime, uint16_t offtime, uint8_t PWM_code )
+{
+ TCNT2 = 0;
+ if(PWM_code) {
+ pinMode(IRLED, OUTPUT);
+ // Fast PWM, setting top limit, divide by 8
+ // Output to pin 3
+ TCCR2A = _BV(COM2A0) | _BV(COM2B1) | _BV(WGM21) | _BV(WGM20);
+ TCCR2B = _BV(WGM22) | _BV(CS21);
+ }
+ else {
+ // However some codes dont use PWM in which case we just turn the IR
+ // LED on for the period of time.
+ digitalWrite(IRLED, HIGH);
+ }
+
+ // Now we wait, allowing the PWM hardware to pulse out the carrier
+ // frequency for the specified 'on' time
+ delay_ten_us(ontime);
+
+ // Now we have to turn it off so disable the PWM output
+ TCCR2A = 0;
+ TCCR2B = 0;
+ // And make sure that the IR LED is off too (since the PWM may have
+ // been stopped while the LED is on!)
+ digitalWrite(IRLED, LOW);
+
+ // Now we wait for the specified 'off' time
+ delay_ten_us(offtime);
+}
+
+/* This is kind of a strange but very useful helper function
+ Because we are using compression, we index to the timer table
+ not with a full 8-bit byte (which is wasteful) but 2 or 3 bits.
+ Once code_ptr is set up to point to the right part of memory,
+ this function will let us read 'count' bits at a time which
+ it does by reading a byte into 'bits_r' and then buffering it. */
+
+uint8_t bitsleft_r = 0;
+uint8_t bits_r=0;
+PGM_P code_ptr;
+
+// we cant read more than 8 bits at a time so dont try!
+uint8_t read_bits(uint8_t count)
+{
+ uint8_t i;
+ uint8_t tmp=0;
+
+ // we need to read back count bytes
+ for (i=0; i> (bitsleft_r)) & 1) << (count-1-i));
+ }
+ // return the selected bits in the LSB part of tmp
+ return tmp;
+}
+
+
+/*
+The C compiler creates code that will transfer all constants into RAM when
+ the microcontroller resets. Since this firmware has a table (powerCodes)
+ that is too large to transfer into RAM, the C compiler needs to be told to
+ keep it in program memory space. This is accomplished by the macro PROGMEM
+ (this is used in the definition for powerCodes). Since the C compiler assumes
+ that constants are in RAM, rather than in program memory, when accessing
+ powerCodes, we need to use the pgm_read_word() and pgm_read_byte macros, and
+ we need to use powerCodes as an address. This is done with PGM_P, defined
+ below.
+ For example, when we start a new powerCode, we first point to it with the
+ following statement:
+ PGM_P thecode_p = pgm_read_word(powerCodes+i);
+ The next read from the powerCode is a byte that indicates the carrier
+ frequency, read as follows:
+ const uint8_t freq = pgm_read_byte(code_ptr++);
+ After that is a byte that tells us how many 'onTime/offTime' pairs we have:
+ const uint8_t numpairs = pgm_read_byte(code_ptr++);
+ The next byte tells us the compression method. Since we are going to use a
+ timing table to keep track of how to pulse the LED, and the tables are
+ pretty short (usually only 4-8 entries), we can index into the table with only
+ 2 to 4 bits. Once we know the bit-packing-size we can decode the pairs
+ const uint8_t bitcompression = pgm_read_byte(code_ptr++);
+ Subsequent reads from the powerCode are n bits (same as the packing size)
+ that index into another table in ROM that actually stores the on/off times
+ const PGM_P time_ptr = (PGM_P)pgm_read_word(code_ptr);
+ */
+
+uint16_t ontime, offtime;
+uint8_t i,num_codes, Loop;
+uint8_t region;
+uint8_t startOver;
+
+#define FALSE 0
+#define TRUE 1
+
+void setup() {
+ Serial.begin(9600);
+
+ TCCR2A = 0;
+ TCCR2B = 0;
+
+ digitalWrite(LED, LOW);
+ digitalWrite(IRLED, LOW);
+ digitalWrite(DBG, LOW); // debug
+ pinMode(LED, OUTPUT);
+ pinMode(IRLED, OUTPUT);
+ pinMode(DBG, OUTPUT); // debug
+ pinMode(REGIONSWITCH, INPUT);
+ pinMode(TRIGGER, INPUT);
+ digitalWrite(REGIONSWITCH, HIGH); //Pull-up
+ digitalWrite(TRIGGER, HIGH);
+
+ delay_ten_us(5000); // Let everything settle for a bit
+
+ // determine region
+ if (digitalRead(REGIONSWITCH)) {
+ region = NA;
+ DEBUGP(putstring_nl("NA"));
+ }
+ else {
+ region = EU;
+ DEBUGP(putstring_nl("EU"));
+ }
+
+ // Indicate how big our database is
+ DEBUGP(putstring("\n\rNA Codesize: ");
+ putnum_ud(num_NAcodes);
+ );
+ DEBUGP(putstring("\n\rEU Codesize: ");
+ putnum_ud(num_EUcodes);
+ );
+
+ // Tell the user what region we're in - 3 flashes is NA, 6 is EU
+ delay_ten_us(65500); // wait maxtime
+ delay_ten_us(65500); // wait maxtime
+ delay_ten_us(65500); // wait maxtime
+ delay_ten_us(65500); // wait maxtime
+ quickflashLEDx(3);
+ if (region == EU) {
+ quickflashLEDx(3);
+ }
+}
+
+void sendAllCodes() {
+Start_transmission:
+ // startOver will become TRUE if the user pushes the Trigger button while transmitting the sequence of all codes
+ startOver = FALSE;
+
+ // determine region from REGIONSWITCH: 1 = NA, 0 = EU
+ if (digitalRead(REGIONSWITCH)) {
+ region = NA;
+ num_codes = num_NAcodes;
+ }
+ else {
+ region = EU;
+ num_codes = num_EUcodes;
+ }
+
+ // for every POWER code in our collection
+ for (i=0 ; i < num_codes; i++) {
+ PGM_P data_ptr;
+
+ // print out the code # we are about to transmit
+ DEBUGP(putstring("\n\r\n\rCode #: ");
+ putnum_ud(i));
+
+ // point to next POWER code, from the right database
+ if (region == NA) {
+ data_ptr = (PGM_P)pgm_read_word(NApowerCodes+i);
+ }
+ else {
+ data_ptr = (PGM_P)pgm_read_word(EUpowerCodes+i);
+ }
+
+ // print out the address in ROM memory we're reading
+ DEBUGP(putstring("\n\rAddr: ");
+ putnum_uh((uint16_t)data_ptr));
+
+ // Read the carrier frequency from the first byte of code structure
+ const uint8_t freq = pgm_read_byte(data_ptr++);
+ // set OCR for Timer1 to output this POWER code's carrier frequency
+ OCR2A = freq;
+ OCR2B = freq / 3; // 33% duty cycle
+
+ // Print out the frequency of the carrier and the PWM settings
+ DEBUGP(putstring("\n\rOCR1: ");
+ putnum_ud(freq);
+ );
+ DEBUGP(uint16_t x = (freq+1) * 2;
+ putstring("\n\rFreq: ");
+ putnum_ud(F_CPU/x);
+ );
+
+ // Get the number of pairs, the second byte from the code struct
+ const uint8_t numpairs = pgm_read_byte(data_ptr++);
+ DEBUGP(putstring("\n\rOn/off pairs: ");
+ putnum_ud(numpairs));
+
+ // Get the number of bits we use to index into the timer table
+ // This is the third byte of the structure
+ const uint8_t bitcompression = pgm_read_byte(data_ptr++);
+ DEBUGP(putstring("\n\rCompression: ");
+ putnum_ud(bitcompression);
+ putstring("\n\r"));
+
+ // Get pointer (address in memory) to pulse-times table
+ // The address is 16-bits (2 byte, 1 word)
+ PGM_P time_ptr = (PGM_P)pgm_read_word(data_ptr);
+ data_ptr+=2;
+ code_ptr = (PGM_P)pgm_read_word(data_ptr);
+
+ // Transmit all codeElements for this POWER code
+ // (a codeElement is an onTime and an offTime)
+ // transmitting onTime means pulsing the IR emitters at the carrier
+ // frequency for the length of time specified in onTime
+ // transmitting offTime means no output from the IR emitters for the
+ // length of time specified in offTime
+
+#if 0
+
+ // print out all of the pulse pairs
+ for (uint8_t k=0; k>2);
+ putstring("\tPair = ");
+ putnum_ud(ontime));
+ DEBUGP(putstring("\t");
+ putnum_ud(offtime));
+ }
+ continue;
+#endif
+
+ // For EACH pair in this code....
+ cli();
+ for (uint8_t k=0; k
+
+
+// The TV-B-Gone for Arduino can use
+// either the EU or the NA database of POWER CODES
+// EU is for Europe, Middle East, Australia, New Zealand, and some countries in Africa and South America
+// NA is for North America, Asia, and the rest of the world not covered by EU
+
+// Two regions!
+#define NA 1
+#define EU 0
+
+// What pins do what
+#define DBG 12
+#define LED 13
+#define IRLED 3
+#define TRIGGER 2
+#define REGIONSWITCH 5
+
+// Lets us calculate the size of the NA/EU databases
+#define NUM_ELEM(x) (sizeof (x) / sizeof (*(x)));
+
+// set define to 0 to turn off debug output
+#define DEBUG 0
+#define DEBUGP(x) if (DEBUG == 1) { x ; }
+
+// Shortcut to insert single, non-optimized-out nop
+#define NOP __asm__ __volatile__ ("nop")
+
+// Tweak this if neccessary to change timing
+#define DELAY_CNT 25
+
+// Makes the codes more readable. the OCRA is actually
+// programmed in terms of 'periods' not 'freqs' - that
+// is, the inverse!
+#define freq_to_timerval(x) (F_CPU / 8 / x - 1)
+
+// The structure of compressed code entries
+struct IrCode {
+ uint8_t timer_val;
+ uint8_t numpairs;
+ uint8_t bitcompression;
+ uint16_t const *times;
+ uint8_t const*codes;
+};
diff --git a/libraries/readme.txt b/libraries/readme.txt
new file mode 100644
index 0000000..a8f1390
--- /dev/null
+++ b/libraries/readme.txt
@@ -0,0 +1 @@
+For information on installing libraries, see: http://arduino.cc/en/Guide/Libraries