// Vader Vambrace Code is based on example code from AnalysIR, and code from
// TVBGone. Additional code was written to interpret the TVBGone database
// entries into the same type of code that the Particle Photon PWM
// transmitter code from AnalysIR uses.
//
// The Vader Vambrace turns the Particle Photon into a TVBGone.
// Plus there are some buttons and LEDs.
/*
* Author: AnalysIR via http://www.AnalysIR.com/
*
* Date: 1st October 2015 V1.0
*
* License: Creative Commons, Attribution-NonCommercial-ShareAlike 4.0 International
* http://creativecommons.org/licenses/by-nc-sa/4.0/
*
* For Commercial use or alternative License: Please contact the Author, via the website above
*
* Attribution: Please credit the Author on all media and provide a link to http://www.AnalysIR.com/
*
* Feedback: We would love to hear about how you use this software & suggestions for improvement.
*
*/
// Mostly taken from main.h in TVBGONE code version 1.2
#include <stdint.h>
#define BIGGEST_NUMPAIRS 136
// Lets us calculate the size of the NA/EU databases
#define NUM_ELEM(x) (sizeof (x) / sizeof (*(x)));
// The structure of compressed code entries
struct IrCode {
uint16_t timer_val; // now just the frequency in Hz
uint8_t numpairs;
uint8_t bitcompression;
uint16_t const *times;
uint8_t codes[BIGGEST_NUMPAIRS];
};
//#include "sendcodes.c"
// Adapt TVbGone compressed data structures to Photon IR transmitting routine.
//
// 2016-01-28 ptw
// This is the function that sends an infrared code on the Photon.
//
// sigArray is an array of durations in microseconds. Even indexed entries
// are marks (carrier transmitted) and odd indexed entries are
// spaces (delay with no transmission).
// sizeArray is the length of sigArray
// khz is the carrier frequency in kilohertz, which must be one of
// 30, 33, 36, 38, 40, 56 kHz. Any other value defaults to 38kHz.
extern void sendRawBuf(unsigned int *sigArray, unsigned int sizeArray, unsigned char kHz);
// The Photon IR sending routines use the UART for transmitting the carrier
// frequency. Unfortunately, that seems to limit the possible carrier
// frequencies to specific values. These are the supported values in kHz.
unsigned char valid_freqs[] = {30, 33, 36, 38, 40, 56};
// Given a precise frequency in Hertz, return the value from valid_freqs[]
// that is closest (in kilohertz).
unsigned char nearest_valid_carrier_frequency_to(unsigned int hz)
{
int i;
// Compare the precise value to the halfway point between valid frequencies.
for (i=0; i < sizeof(valid_freqs)-1; i++) {
if (hz < (valid_freqs[i]+valid_freqs[i+1])*1000/2)
return valid_freqs[i];
}
return valid_freqs[i];
}
// This array of pointers to structures is the key to the TVbGone database.
extern const struct IrCode *NApowerCodes[];
extern const uint8_t num_NAcodes;
// Unpacking routines for the compressed format. Call init_unpacker() at
// the beginning of each signal, then call unpack_next_value() to get each successive
// value. The two routines share these global variables to maintain state.
int bits_per_pair;
uint8_t const *next_byte_to_unpack;
uint8_t this_byte;
int bits_left_in_this_byte;
void init_unpacker(uint8_t bitcompression, uint8_t const *compressed_codes)
{
bits_per_pair = bitcompression;
next_byte_to_unpack = compressed_codes;
bits_left_in_this_byte = 0;
}
int unpack_next_value(void)
{
int value = 0;
for (int i=0; i < bits_per_pair; i++) {
// Get a new byte to unpack if we're out of bits in this_byte
if (bits_left_in_this_byte <= 0) {
this_byte = *next_byte_to_unpack++;
bits_left_in_this_byte = 8;
}
// Grab a bit from this_byte
int bit = !! (this_byte & 0x80);
this_byte = this_byte << 1;
bits_left_in_this_byte--;
// Pack the bit into our output value
value = (value << 1) | bit;
}
return value;
}
// Translate an infrared control signal from the TVbGone compressed format
// to the raw format we use.
//
// In compressed format, each entry is a few bits, packed into the bytes
// of the codes array. Those few bits index a table (provided as the array
// called times) which gives mark and space durations for that signal.
//
// In the raw format, we just list the durations: mark, space, mark, space, ...
//
// We are guaranteed that raw_durations is long enough to hold the results.
void translate_signal( unsigned int *raw_durations, // output array buffer
uint8_t numpairs, // number of mark+space pairs
uint8_t bitcompression, // number of bits per pair
uint16_t const *times_table, // table of duration values
uint8_t const compressed_codes[] // packed code indices
)
{
init_unpacker(bitcompression, compressed_codes);
for (int i=0; i < numpairs; i++) {
int pair_index = unpack_next_value();
unsigned int mark_duration = 10 * times_table[pair_index * 2];
unsigned int space_duration = 10 * times_table[pair_index * 2 + 1];
// TVbGone encodes durations in units of 10us!
*raw_durations++ = mark_duration;
*raw_durations++ = space_duration;
}
}
// Send a code from the TVbGone database
void send_one_code(const struct IrCode *code)
{
unsigned char khz = nearest_valid_carrier_frequency_to(code->timer_val);
unsigned int sizeArray = code->numpairs * 2;
unsigned int sigArray[BIGGEST_NUMPAIRS * 2];
translate_signal(sigArray, code->numpairs, code->bitcompression, code->times, code->codes);
sendRawBuf(sigArray, sizeArray, khz);
}
// Here is the main entry point to send all the infrared control codes.
void send_all_codes(unsigned int ms_delay_between_codes)
{
for (int i=0; i < num_NAcodes; i++) {
send_one_code(NApowerCodes[i]);
delay(ms_delay_between_codes);
}
}
// File taken from TVBGONE kit code version 1.2 and adapted for
// use on non-memory-constrained processor.
//#include "codes.h" //testing particle.ignore
// We want the North American codes only
#define NA_CODES
// PROGMEM keeps the data in ROM (flash) instead of copying it to RAM.
// This is important if RAM is scarce. Here, we don't need it, so define
// the macro to do nothing.
#define PROGMEM
// Originally the data structure stored a hardware-specific register value
// for the carrier frequency. We need to just store the frequency instead.
#define freq_to_timerval(x) x
//Codes captured from Generation 3 TV-B-Gone by Limor Fried & Mitch Altman
// table of POWER codes
#ifdef NA_CODES
const uint16_t code_na000Times[] PROGMEM = {
60, 60,
60, 2700,
120, 60,
240, 60,
};
const struct IrCode code_na000Code PROGMEM = {
freq_to_timerval(38400),
26, // # of pairs
2, // # of bits per index
code_na000Times,
{
0xE2,
0x20,
0x80,
0x78,
0x88,
0x20,
0x10,
}
};
const uint16_t code_na001Times[] PROGMEM = {
50, 100,
50, 200,
50, 800,
400, 400,
};
const struct IrCode code_na001Code PROGMEM = {
freq_to_timerval(57143),
52, // # of pairs
2, // # of bits per index
code_na001Times,
{
0xD5,
0x41,
0x11,
0x00,
0x14,
0x44,
0x6D,
0x54,
0x11,
0x10,
0x01,
0x44,
0x45,
}
};
const uint16_t code_na002Times[] PROGMEM = {
42, 46,
42, 133,
42, 7519,
347, 176,
347, 177,
};
const struct IrCode code_na002Code PROGMEM = {
freq_to_timerval(37037),
100, // # of pairs
3, // # of bits per index
code_na002Times,
{
0x60,
0x80,
0x00,
0x00,
0x00,
0x08,
0x00,
0x00,
0x00,
0x20,
0x00,
0x00,
0x04,
0x12,
0x48,
0x04,
0x12,
0x48,
0x2A,
0x02,
0x00,
0x00,
0x00,
0x00,
0x20,
0x00,
0x00,
0x00,
0x80,
0x00,
0x00,
0x10,
0x49,
0x20,
0x10,
0x49,
0x20,
0x80,
}
};
const uint16_t code_na003Times[] PROGMEM = {
26, 185,
27, 80,
27, 185,
27, 4549,
};
const struct IrCode code_na003Code PROGMEM = {
freq_to_timerval(38610),
64, // # of pairs
2, // # of bits per index
code_na003Times,
{
0x15,
0x5A,
0x65,
0x67,
0x95,
0x65,
0x9A,
0x9B,
0x95,
0x5A,
0x65,
0x67,
0x95,
0x65,
0x9A,
0x99,
}
};
const uint16_t code_na004Times[] PROGMEM = {
55, 57,
55, 170,
55, 3949,
55, 9623,
56, 0,
898, 453,
900, 226,
};
const struct IrCode code_na004Code PROGMEM = {
freq_to_timerval(38610),
38, // # of pairs
3, // # of bits per index
code_na004Times,
{
0xA0,
0x00,
0x01,
0x04,
0x92,
0x48,
0x20,
0x80,
0x40,
0x04,
0x12,
0x09,
0x2B,
0x3D,
0x00,
}
};
const uint16_t code_na005Times[] PROGMEM = {
88, 90,
88, 91,
88, 181,
88, 8976,
177, 91,
};
const struct IrCode code_na005Code PROGMEM = {
freq_to_timerval(35714),
24, // # of pairs
3, // # of bits per index
code_na005Times,
{
0x10,
0x92,
0x49,
0x46,
0x33,
0x09,
0x24,
0x94,
0x60,
}
};
const uint16_t code_na006Times[] PROGMEM = {
50, 62,
50, 172,
50, 4541,
448, 466,
450, 465,
};
const struct IrCode code_na006Code PROGMEM = {
freq_to_timerval(38462),
68, // # of pairs
3, // # of bits per index
code_na006Times,
{
0x64,
0x90,
0x00,
0x04,
0x90,
0x00,
0x00,
0x80,
0x00,
0x04,
0x12,
0x49,
0x2A,
0x12,
0x40,
0x00,
0x12,
0x40,
0x00,
0x02,
0x00,
0x00,
0x10,
0x49,
0x24,
0x90,
}
};
const uint16_t code_na007Times[] PROGMEM = {
49, 49,
49, 50,
49, 410,
49, 510,
49, 12107,
};
const struct IrCode code_na007Code PROGMEM = {
freq_to_timerval(39216),
34, // # of pairs
3, // # of bits per index
code_na007Times,
{
0x09,
0x94,
0x53,
0x29,
0x94,
0xD9,
0x85,
0x32,
0x8A,
0x65,
0x32,
0x9B,
0x20,
}
};
const uint16_t code_na008Times[] PROGMEM = {
56, 58,
56, 170,
56, 4011,
898, 450,
900, 449,
};
const struct IrCode code_na008Code PROGMEM = {
freq_to_timerval(38462),
68, // # of pairs
3, // # of bits per index
code_na008Times,
{
0x64,
0x00,
0x49,
0x00,
0x92,
0x00,
0x20,
0x82,
0x01,
0x04,
0x10,
0x48,
0x2A,
0x10,
0x01,
0x24,
0x02,
0x48,
0x00,
0x82,
0x08,
0x04,
0x10,
0x41,
0x20,
0x90,
}
};
const uint16_t code_na009Times[] PROGMEM = {
53, 56,
53, 171,
53, 3950,
53, 9599,
898, 451,
900, 226,
};
const struct IrCode code_na009Code PROGMEM = {
freq_to_timerval(38462),
38, // # of pairs
3, // # of bits per index
code_na009Times,
{
0x84,
0x90,
0x00,
0x20,
0x80,
0x08,
0x00,
0x00,
0x09,
0x24,
0x92,
0x40,
0x0A,
0xBA,
0x40,
}
};
const uint16_t code_na010Times[] PROGMEM = {
51, 55,
51, 158,
51, 2286,
841, 419,
};
const struct IrCode code_na010Code PROGMEM = {
freq_to_timerval(38462),
52, // # of pairs
2, // # of bits per index
code_na010Times,
{
0xD4,
0x00,
0x15,
0x10,
0x25,
0x00,
0x05,
0x44,
0x09,
0x40,
0x01,
0x51,
0x01,
}
};
const uint16_t code_na011Times[] PROGMEM = {
55, 55,
55, 172,
55, 4039,
55, 9348,
56, 0,
884, 442,
885, 225,
};
const struct IrCode code_na011Code PROGMEM = {
freq_to_timerval(38462),
38, // # of pairs
3, // # of bits per index
code_na011Times,
{
0xA0,
0x00,
0x41,
0x04,
0x92,
0x08,
0x24,
0x90,
0x40,
0x00,
0x02,
0x09,
0x2B,
0x3D,
0x00,
}
};
const uint16_t code_na012Times[] PROGMEM = {
81, 87,
81, 254,
81, 3280,
331, 336,
331, 337,
};
const struct IrCode code_na012Code PROGMEM = {
freq_to_timerval(38462),
52, // # of pairs
3, // # of bits per index
code_na012Times,
{
0x64,
0x12,
0x08,
0x24,
0x00,
0x08,
0x20,
0x10,
0x09,
0x2A,
0x10,
0x48,
0x20,
0x90,
0x00,
0x20,
0x80,
0x40,
0x24,
0x90,
}
};
const uint16_t code_na013Times[] PROGMEM = {
53, 55,
53, 167,
53, 2304,
53, 9369,
893, 448,
895, 447,
};
const struct IrCode code_na013Code PROGMEM = {
freq_to_timerval(38462),
48, // # of pairs
3, // # of bits per index
code_na013Times,
{
0x80,
0x12,
0x40,
0x04,
0x00,
0x09,
0x00,
0x12,
0x41,
0x24,
0x82,
0x01,
0x00,
0x10,
0x48,
0x24,
0xAA,
0xE8,
}
};
/* Duplicate timing table, same as na004 !
const uint16_t code_na014Times[] PROGMEM = {
55, 57,
55, 170,
55, 3949,
55, 9623,
56, 0,
898, 453,
900, 226,
};
*/
const struct IrCode code_na014Code PROGMEM = {
freq_to_timerval(38462),
38, // # of pairs
3, // # of bits per index
code_na004Times,
{
0xA0,
0x00,
0x09,
0x04,
0x92,
0x40,
0x24,
0x80,
0x00,
0x00,
0x12,
0x49,
0x2B,
0x3D,
0x00,
}
};
/* Duplicate timing table, same as na004 !
const uint16_t code_na015Times[] PROGMEM = {
55, 57,
55, 170,
55, 3949,
55, 9623,
56, 0,
898, 453,
900, 226,
};
*/
const struct IrCode code_na015Code PROGMEM = {
freq_to_timerval(38462),
38, // # of pairs
3, // # of bits per index
code_na004Times,
{
0xA0,
0x80,
0x01,
0x04,
0x12,
0x48,
0x24,
0x00,
0x00,
0x00,
0x92,
0x49,
0x2B,
0x3D,
0x00,
}
};
const uint16_t code_na016Times[] PROGMEM = {
28, 90,
28, 211,
28, 2507,
};
const struct IrCode code_na016Code PROGMEM = {
freq_to_timerval(34483),
34, // # of pairs
2, // # of bits per index
code_na016Times,
{
0x54,
0x04,
0x10,
0x00,
0x95,
0x01,
0x04,
0x00,
0x10,
}
};
const uint16_t code_na017Times[] PROGMEM = {
56, 57,
56, 175,
56, 4150,
56, 9499,
898, 227,
898, 449,
};
const struct IrCode code_na017Code PROGMEM = {
freq_to_timerval(40000),
38, // # of pairs
3, // # of bits per index
code_na017Times,
{
0xA0,
0x02,
0x48,
0x04,
0x90,
0x01,
0x20,
0x80,
0x40,
0x04,
0x12,
0x09,
0x2A,
0x38,
0x00,
}
};
const uint16_t code_na018Times[] PROGMEM = {
51, 55,
51, 161,
51, 2566,
849, 429,
849, 430,
};
const struct IrCode code_na018Code PROGMEM = {
freq_to_timerval(38462),
136, // # of pairs
3, // # of bits per index
code_na018Times,
{
0x60,
0x82,
0x08,
0x24,
0x10,
0x41,
0x00,
0x12,
0x40,
0x04,
0x80,
0x09,
0x2A,
0x02,
0x08,
0x20,
0x90,
0x41,
0x04,
0x00,
0x49,
0x00,
0x12,
0x00,
0x24,
0xA8,
0x08,
0x20,
0x82,
0x41,
0x04,
0x10,
0x01,
0x24,
0x00,
0x48,
0x00,
0x92,
0xA0,
0x20,
0x82,
0x09,
0x04,
0x10,
0x40,
0x04,
0x90,
0x01,
0x20,
0x02,
0x48,
}
};
const uint16_t code_na019Times[] PROGMEM = {
40, 42,
40, 124,
40, 4601,
325, 163,
326, 163,
};
const struct IrCode code_na019Code PROGMEM = {
freq_to_timerval(38462),
100, // # of pairs
3, // # of bits per index
code_na019Times,
{
0x60,
0x10,
0x40,
0x04,
0x80,
0x09,
0x00,
0x00,
0x00,
0x00,
0x10,
0x00,
0x20,
0x10,
0x00,
0x20,
0x80,
0x00,
0x0A,
0x00,
0x41,
0x00,
0x12,
0x00,
0x24,
0x00,
0x00,
0x00,
0x00,
0x40,
0x00,
0x80,
0x40,
0x00,
0x82,
0x00,
0x00,
0x00,
}
};
const uint16_t code_na020Times[] PROGMEM = {
60, 55,
60, 163,
60, 4099,
60, 9698,
61, 0,
898, 461,
900, 230,
};
const struct IrCode code_na020Code PROGMEM = {
freq_to_timerval(38462),
38, // # of pairs
3, // # of bits per index
code_na020Times,
{
0xA0,
0x10,
0x00,
0x04,
0x82,
0x49,
0x20,
0x02,
0x00,
0x04,
0x90,
0x49,
0x2B,
0x3D,
0x00,
}
};
const uint16_t code_na021Times[] PROGMEM = {
48, 52,
48, 160,
48, 400,
48, 2335,
799, 400,
};
const struct IrCode code_na021Code PROGMEM = {
freq_to_timerval(38462),
38, // # of pairs
3, // # of bits per index
code_na021Times,
{
0x80,
0x10,
0x40,
0x08,
0x82,
0x08,
0x01,
0xC0,
0x08,
0x20,
0x04,
0x41,
0x04,
0x00,
0x00,
}
};
...
This file has been truncated, please download it to see its full contents.
Comments