From 413f52c0089fb6dbd5e0c94ffd543477b10fc6b9 Mon Sep 17 00:00:00 2001 From: MangaValk Date: Mon, 17 Feb 2014 11:44:17 +0100 Subject: [PATCH] FireFly library: variant kept in the 2014 GitLab archive GPS include disabled, out-of-reach flag instead of the 7-segment error. Exact date unknown; dated at the archive's first commit (Feb 2014). --- .../2012-library/hexapod/IRremote.cpp | 1444 ++++++++--------- .../firmware/2012-library/hexapod/IRremote.h | 202 +-- .../2012-library/hexapod/IRremoteInt.h | 796 ++++----- .../hexapod/InverseKinemetics.cpp | 18 +- .../firmware/2012-library/hexapod/Segment.cpp | 166 +- .../firmware/2012-library/hexapod/Segment.h | 38 +- .../firmware/2012-library/hexapod/TinyGPS.h | 2 +- .../firmware/2012-library/hexapod/WiiChuck.h | 378 ++--- .../hexapod/concept_informatie.txt | 122 +- .../firmware/2012-library/hexapod/hexapod.h | 2 +- 10 files changed, 1585 insertions(+), 1583 deletions(-) diff --git a/2011-firefly-mega-ssc32/firmware/2012-library/hexapod/IRremote.cpp b/2011-firefly-mega-ssc32/firmware/2012-library/hexapod/IRremote.cpp index 8395c3a..6b58705 100644 --- a/2011-firefly-mega-ssc32/firmware/2012-library/hexapod/IRremote.cpp +++ b/2011-firefly-mega-ssc32/firmware/2012-library/hexapod/IRremote.cpp @@ -1,722 +1,722 @@ -/* - * IRremote - * Version 0.11 August, 2009 - * Copyright 2009 Ken Shirriff - * For details, see http://arcfn.com/2009/08/multi-protocol-infrared-remote-library.html - * - * Modified by Paul Stoffregen to support other boards and timers - * - * 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 "IRremote.h" -#include "IRremoteInt.h" - -// Provides ISR -#include - -volatile irparams_t irparams; - -// These versions of MATCH, MATCH_MARK, and MATCH_SPACE are only for debugging. -// To use them, set DEBUG in IRremoteInt.h -// Normally macros are used for efficiency -#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 - -void IRsend::sendNEC(unsigned long data, int nbits) -{ - enableIROut(38); - mark(NEC_HDR_MARK); - space(NEC_HDR_SPACE); - for (int i = 0; i < nbits; i++) { - if (data & TOPBIT) { - mark(NEC_BIT_MARK); - space(NEC_ONE_SPACE); - } - else { - mark(NEC_BIT_MARK); - space(NEC_ZERO_SPACE); - } - data <<= 1; - } - mark(NEC_BIT_MARK); - space(0); -} - -void IRsend::sendSony(unsigned long data, int nbits) { - enableIROut(40); - mark(SONY_HDR_MARK); - space(SONY_HDR_SPACE); - data = data << (32 - nbits); - for (int i = 0; i < nbits; i++) { - if (data & TOPBIT) { - mark(SONY_ONE_MARK); - space(SONY_HDR_SPACE); - } - else { - mark(SONY_ZERO_MARK); - space(SONY_HDR_SPACE); - } - data <<= 1; - } -} - -void IRsend::sendRaw(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 -} - -// Note: first bit must be a one (start bit) -void IRsend::sendRC5(unsigned long data, int nbits) -{ - enableIROut(36); - data = data << (32 - nbits); - mark(RC5_T1); // First start bit - space(RC5_T1); // Second start bit - mark(RC5_T1); // Second start bit - for (int i = 0; i < nbits; i++) { - if (data & TOPBIT) { - space(RC5_T1); // 1 is space, then mark - mark(RC5_T1); - } - else { - mark(RC5_T1); - space(RC5_T1); - } - data <<= 1; - } - space(0); // Turn off at end -} - -// Caller needs to take care of flipping the toggle bit -void IRsend::sendRC6(unsigned long data, int nbits) -{ - enableIROut(36); - data = data << (32 - nbits); - mark(RC6_HDR_MARK); - space(RC6_HDR_SPACE); - mark(RC6_T1); // start bit - space(RC6_T1); - int t; - for (int i = 0; i < nbits; i++) { - if (i == 3) { - // double-wide trailer bit - t = 2 * RC6_T1; - } - else { - t = RC6_T1; - } - if (data & TOPBIT) { - mark(t); - space(t); - } - else { - space(t); - mark(t); - } - - data <<= 1; - } - space(0); // Turn off at end -} - -void IRsend::mark(int time) { - // Sends an IR mark for the specified number of microseconds. - // The mark output is modulated at the PWM frequency. - TIMER_ENABLE_PWM; // Enable pin 3 PWM output - delayMicroseconds(time); -} - -/* Leave pin off for time (given in microseconds) */ -void IRsend::space(int time) { - // Sends an IR space for the specified number of microseconds. - // A space is no output, so the PWM output is disabled. - TIMER_DISABLE_PWM; // Disable pin 3 PWM output - delayMicroseconds(time); -} - -void IRsend::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 - - // COM2A = 00: disconnect OC2A - // COM2B = 00: disconnect OC2B; to send signal set to 10: OC2B non-inverted - // WGM2 = 101: phase-correct PWM with OCRA as top - // CS2 = 000: no prescaling - // The top value for the timer. The modulation frequency will be SYSCLOCK / 2 / OCR2A. - TIMER_CONFIG_KHZ(khz); -} - -IRrecv::IRrecv(int recvpin) -{ - irparams.recvpin = recvpin; - irparams.blinkflag = 0; -} - -// initialization -void IRrecv::enableIRIn() { - cli(); - // setup pulse clock timer interrupt - //Prescale /8 (16M/8 = 0.5 microseconds per tick) - // Therefore, the timer interval can range from 0.5 to 128 microseconds - // depending on the reset value (255 to 0) - TIMER_CONFIG_NORMAL(); - - //Timer2 Overflow Interrupt Enable - TIMER_ENABLE_INTR; - - TIMER_RESET; - - sei(); // enable interrupts - - // 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); -} - -// 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; - - uint8_t irdata = (uint8_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 == 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 == 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 == 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 == MARK) { // reset gap timer - irparams.timer = 0; - } - break; - } - - if (irparams.blinkflag) { - if (irdata == MARK) { - BLINKLED_ON(); // turn pin 13 LED on - } - else { - BLINKLED_OFF(); // turn pin 13 LED off - } - } -} - -void IRrecv::resume() { - irparams.rcvstate = STATE_IDLE; - irparams.rawlen = 0; -} - - - -// Decodes the received IR message -// Returns 0 if no data ready, 1 if data ready. -// Results of decoding are stored in results -int IRrecv::decode(decode_results *results) { - results->rawbuf = irparams.rawbuf; - results->rawlen = irparams.rawlen; - if (irparams.rcvstate != STATE_STOP) { - return ERR; - } -#ifdef DEBUG - Serial.println("Attempting NEC decode"); -#endif - if (decodeNEC(results)) { - return DECODED; - } -#ifdef DEBUG - Serial.println("Attempting Sony decode"); -#endif - if (decodeSony(results)) { - return DECODED; - } -#ifdef DEBUG - Serial.println("Attempting RC5 decode"); -#endif - if (decodeRC5(results)) { - return DECODED; - } -#ifdef DEBUG - Serial.println("Attempting RC6 decode"); -#endif - if (decodeRC6(results)) { - return DECODED; - } - // decodeHash returns a hash on any input. - // Thus, it needs to be last in the list. - // If you add any decodes, add them before this. - if (decodeHash(results)) { - return DECODED; - } - // Throw away and start over - resume(); - return ERR; -} - -long IRrecv::decodeNEC(decode_results *results) { - long data = 0; - int offset = 1; // Skip first space - // Initial mark - if (!MATCH_MARK(results->rawbuf[offset], NEC_HDR_MARK)) { - return ERR; - } - offset++; - // Check for repeat - if (irparams.rawlen == 4 && - MATCH_SPACE(results->rawbuf[offset], NEC_RPT_SPACE) && - MATCH_MARK(results->rawbuf[offset+1], NEC_BIT_MARK)) { - results->bits = 0; - results->value = REPEAT; - results->decode_type = NEC; - return DECODED; - } - if (irparams.rawlen < 2 * NEC_BITS + 4) { - return ERR; - } - // Initial space - if (!MATCH_SPACE(results->rawbuf[offset], NEC_HDR_SPACE)) { - return ERR; - } - offset++; - for (int i = 0; i < NEC_BITS; i++) { - if (!MATCH_MARK(results->rawbuf[offset], NEC_BIT_MARK)) { - return ERR; - } - offset++; - if (MATCH_SPACE(results->rawbuf[offset], NEC_ONE_SPACE)) { - data = (data << 1) | 1; - } - else if (MATCH_SPACE(results->rawbuf[offset], NEC_ZERO_SPACE)) { - data <<= 1; - } - else { - return ERR; - } - offset++; - } - // Success - results->bits = NEC_BITS; - results->value = data; - results->decode_type = NEC; - return DECODED; -} - -long IRrecv::decodeSony(decode_results *results) { - long data = 0; - if (irparams.rawlen < 2 * SONY_BITS + 2) { - return ERR; - } - int offset = 1; // Skip first space - // Initial mark - if (!MATCH_MARK(results->rawbuf[offset], SONY_HDR_MARK)) { - return ERR; - } - offset++; - - while (offset + 1 < irparams.rawlen) { - if (!MATCH_SPACE(results->rawbuf[offset], SONY_HDR_SPACE)) { - break; - } - offset++; - if (MATCH_MARK(results->rawbuf[offset], SONY_ONE_MARK)) { - data = (data << 1) | 1; - } - else if (MATCH_MARK(results->rawbuf[offset], SONY_ZERO_MARK)) { - data <<= 1; - } - else { - return ERR; - } - offset++; - } - - // Success - results->bits = (offset - 1) / 2; - if (results->bits < 12) { - results->bits = 0; - return ERR; - } - results->value = data; - results->decode_type = SONY; - return DECODED; -} - -// 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 -1 for error (measured time interval is not a multiple of t1). -int IRrecv::getRClevel(decode_results *results, int *offset, int *used, int t1) { - if (*offset >= results->rawlen) { - // After end of recorded buffer, assume SPACE. - return SPACE; - } - int width = results->rawbuf[*offset]; - int val = ((*offset) % 2) ? MARK : 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 -1; - } - - (*used)++; - if (*used >= avail) { - *used = 0; - (*offset)++; - } -#ifdef DEBUG - if (val == MARK) { - Serial.println("MARK"); - } - else { - Serial.println("SPACE"); - } -#endif - return val; -} - -long IRrecv::decodeRC5(decode_results *results) { - if (irparams.rawlen < MIN_RC5_SAMPLES + 2) { - return ERR; - } - int offset = 1; // Skip gap space - long data = 0; - int used = 0; - // Get start bits - if (getRClevel(results, &offset, &used, RC5_T1) != MARK) return ERR; - if (getRClevel(results, &offset, &used, RC5_T1) != SPACE) return ERR; - if (getRClevel(results, &offset, &used, RC5_T1) != MARK) return ERR; - int nbits; - for (nbits = 0; offset < irparams.rawlen; nbits++) { - int levelA = getRClevel(results, &offset, &used, RC5_T1); - int levelB = getRClevel(results, &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 ERR; - } - } - - // Success - results->bits = nbits; - results->value = data; - results->decode_type = RC5; - return DECODED; -} - -long IRrecv::decodeRC6(decode_results *results) { - if (results->rawlen < MIN_RC6_SAMPLES) { - return ERR; - } - int offset = 1; // Skip first space - // Initial mark - if (!MATCH_MARK(results->rawbuf[offset], RC6_HDR_MARK)) { - return ERR; - } - offset++; - if (!MATCH_SPACE(results->rawbuf[offset], RC6_HDR_SPACE)) { - return ERR; - } - offset++; - long data = 0; - int used = 0; - // Get start bit (1) - if (getRClevel(results, &offset, &used, RC6_T1) != MARK) return ERR; - if (getRClevel(results, &offset, &used, RC6_T1) != SPACE) return ERR; - int nbits; - for (nbits = 0; offset < results->rawlen; nbits++) { - int levelA, levelB; // Next two levels - levelA = getRClevel(results, &offset, &used, RC6_T1); - if (nbits == 3) { - // T bit is double wide; make sure second half matches - if (levelA != getRClevel(results, &offset, &used, RC6_T1)) return ERR; - } - levelB = getRClevel(results, &offset, &used, RC6_T1); - if (nbits == 3) { - // T bit is double wide; make sure second half matches - if (levelB != getRClevel(results, &offset, &used, RC6_T1)) return ERR; - } - 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 ERR; // Error - } - } - // Success - results->bits = nbits; - results->value = data; - results->decode_type = RC6; - return DECODED; -} - -/* ----------------------------------------------------------------------- - * hashdecode - 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. - * - * The algorithm: look at the sequence of MARK signals, and see if each one - * is shorter (0), the same length (1), or longer (2) than the previous. - * Do the same with the SPACE signals. Hszh the resulting sequence of 0's, - * 1's, and 2's to a 32-bit value. This will give a unique value for each - * different code (probably), for most code systems. - * - * http://arcfn.com/2010/01/using-arbitrary-remotes-with-arduino.html - */ - -// Compare two tick values, returning 0 if newval is shorter, -// 1 if newval is equal, and 2 if newval is longer -// Use a tolerance of 20% -int IRrecv::compare(unsigned int oldval, unsigned int newval) { - if (newval < oldval * .8) { - return 0; - } - else if (oldval < newval * .8) { - return 2; - } - else { - return 1; - } -} - -// Use FNV hash algorithm: http://isthe.com/chongo/tech/comp/fnv/#FNV-param -#define FNV_PRIME_32 16777619 -#define FNV_BASIS_32 2166136261 - -/* Converts the raw code values into a 32-bit hash code. - * Hopefully this code is unique for each button. - * This isn't a "real" decoding, just an arbitrary value. - */ -long IRrecv::decodeHash(decode_results *results) { - // Require at least 6 samples to prevent triggering on noise - if (results->rawlen < 6) { - return ERR; - } - long hash = FNV_BASIS_32; - for (int i = 1; i+2 < results->rawlen; i++) { - int value = compare(results->rawbuf[i], results->rawbuf[i+2]); - // Add value into the hash - hash = (hash * FNV_PRIME_32) ^ value; - } - results->value = hash; - results->bits = 32; - results->decode_type = UNKNOWN; - return DECODED; -} - -/* Sharp and DISH support by Todd Treece ( http://unionbridge.org/design/ircommand ) - -The Dish send function needs to be repeated 4 times, and the Sharp function -has the necessary repeat built in because of the need to invert the signal. - -Sharp protocol documentation: -http://www.sbprojects.com/knowledge/ir/sharp.htm - -Here are the LIRC files that I found that seem to match the remote codes -from the oscilloscope: - -Sharp LCD TV: -http://lirc.sourceforge.net/remotes/sharp/GA538WJSA - -DISH NETWORK (echostar 301): -http://lirc.sourceforge.net/remotes/echostar/301_501_3100_5100_58xx_59xx - -For the DISH codes, only send the last for characters of the hex. -i.e. use 0x1C10 instead of 0x0000000000001C10 which is listed in the -linked LIRC file. -*/ - -void IRsend::sendSharp(unsigned long data, int nbits) { - unsigned long invertdata = data ^ SHARP_TOGGLE_MASK; - enableIROut(38); - for (int i = 0; i < nbits; i++) { - if (data & 0x4000) { - mark(SHARP_BIT_MARK); - space(SHARP_ONE_SPACE); - } - else { - mark(SHARP_BIT_MARK); - space(SHARP_ZERO_SPACE); - } - data <<= 1; - } - - mark(SHARP_BIT_MARK); - space(SHARP_ZERO_SPACE); - delay(46); - for (int i = 0; i < nbits; i++) { - if (invertdata & 0x4000) { - mark(SHARP_BIT_MARK); - space(SHARP_ONE_SPACE); - } - else { - mark(SHARP_BIT_MARK); - space(SHARP_ZERO_SPACE); - } - invertdata <<= 1; - } - mark(SHARP_BIT_MARK); - space(SHARP_ZERO_SPACE); - delay(46); -} - -void IRsend::sendDISH(unsigned long data, int nbits) -{ - enableIROut(56); - mark(DISH_HDR_MARK); - space(DISH_HDR_SPACE); - for (int i = 0; i < nbits; i++) { - if (data & DISH_TOP_BIT) { - mark(DISH_BIT_MARK); - space(DISH_ONE_SPACE); - } - else { - mark(DISH_BIT_MARK); - space(DISH_ZERO_SPACE); - } - data <<= 1; - } -} +/* + * IRremote + * Version 0.11 August, 2009 + * Copyright 2009 Ken Shirriff + * For details, see http://arcfn.com/2009/08/multi-protocol-infrared-remote-library.html + * + * Modified by Paul Stoffregen to support other boards and timers + * + * 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 "IRremote.h" +#include "IRremoteInt.h" + +// Provides ISR +#include + +volatile irparams_t irparams; + +// These versions of MATCH, MATCH_MARK, and MATCH_SPACE are only for debugging. +// To use them, set DEBUG in IRremoteInt.h +// Normally macros are used for efficiency +#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 + +void IRsend::sendNEC(unsigned long data, int nbits) +{ + enableIROut(38); + mark(NEC_HDR_MARK); + space(NEC_HDR_SPACE); + for (int i = 0; i < nbits; i++) { + if (data & TOPBIT) { + mark(NEC_BIT_MARK); + space(NEC_ONE_SPACE); + } + else { + mark(NEC_BIT_MARK); + space(NEC_ZERO_SPACE); + } + data <<= 1; + } + mark(NEC_BIT_MARK); + space(0); +} + +void IRsend::sendSony(unsigned long data, int nbits) { + enableIROut(40); + mark(SONY_HDR_MARK); + space(SONY_HDR_SPACE); + data = data << (32 - nbits); + for (int i = 0; i < nbits; i++) { + if (data & TOPBIT) { + mark(SONY_ONE_MARK); + space(SONY_HDR_SPACE); + } + else { + mark(SONY_ZERO_MARK); + space(SONY_HDR_SPACE); + } + data <<= 1; + } +} + +void IRsend::sendRaw(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 +} + +// Note: first bit must be a one (start bit) +void IRsend::sendRC5(unsigned long data, int nbits) +{ + enableIROut(36); + data = data << (32 - nbits); + mark(RC5_T1); // First start bit + space(RC5_T1); // Second start bit + mark(RC5_T1); // Second start bit + for (int i = 0; i < nbits; i++) { + if (data & TOPBIT) { + space(RC5_T1); // 1 is space, then mark + mark(RC5_T1); + } + else { + mark(RC5_T1); + space(RC5_T1); + } + data <<= 1; + } + space(0); // Turn off at end +} + +// Caller needs to take care of flipping the toggle bit +void IRsend::sendRC6(unsigned long data, int nbits) +{ + enableIROut(36); + data = data << (32 - nbits); + mark(RC6_HDR_MARK); + space(RC6_HDR_SPACE); + mark(RC6_T1); // start bit + space(RC6_T1); + int t; + for (int i = 0; i < nbits; i++) { + if (i == 3) { + // double-wide trailer bit + t = 2 * RC6_T1; + } + else { + t = RC6_T1; + } + if (data & TOPBIT) { + mark(t); + space(t); + } + else { + space(t); + mark(t); + } + + data <<= 1; + } + space(0); // Turn off at end +} + +void IRsend::mark(int time) { + // Sends an IR mark for the specified number of microseconds. + // The mark output is modulated at the PWM frequency. + TIMER_ENABLE_PWM; // Enable pin 3 PWM output + delayMicroseconds(time); +} + +/* Leave pin off for time (given in microseconds) */ +void IRsend::space(int time) { + // Sends an IR space for the specified number of microseconds. + // A space is no output, so the PWM output is disabled. + TIMER_DISABLE_PWM; // Disable pin 3 PWM output + delayMicroseconds(time); +} + +void IRsend::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 + + // COM2A = 00: disconnect OC2A + // COM2B = 00: disconnect OC2B; to send signal set to 10: OC2B non-inverted + // WGM2 = 101: phase-correct PWM with OCRA as top + // CS2 = 000: no prescaling + // The top value for the timer. The modulation frequency will be SYSCLOCK / 2 / OCR2A. + TIMER_CONFIG_KHZ(khz); +} + +IRrecv::IRrecv(int recvpin) +{ + irparams.recvpin = recvpin; + irparams.blinkflag = 0; +} + +// initialization +void IRrecv::enableIRIn() { + cli(); + // setup pulse clock timer interrupt + //Prescale /8 (16M/8 = 0.5 microseconds per tick) + // Therefore, the timer interval can range from 0.5 to 128 microseconds + // depending on the reset value (255 to 0) + TIMER_CONFIG_NORMAL(); + + //Timer2 Overflow Interrupt Enable + TIMER_ENABLE_INTR; + + TIMER_RESET; + + sei(); // enable interrupts + + // 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); +} + +// 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; + + uint8_t irdata = (uint8_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 == 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 == 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 == 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 == MARK) { // reset gap timer + irparams.timer = 0; + } + break; + } + + if (irparams.blinkflag) { + if (irdata == MARK) { + BLINKLED_ON(); // turn pin 13 LED on + } + else { + BLINKLED_OFF(); // turn pin 13 LED off + } + } +} + +void IRrecv::resume() { + irparams.rcvstate = STATE_IDLE; + irparams.rawlen = 0; +} + + + +// Decodes the received IR message +// Returns 0 if no data ready, 1 if data ready. +// Results of decoding are stored in results +int IRrecv::decode(decode_results *results) { + results->rawbuf = irparams.rawbuf; + results->rawlen = irparams.rawlen; + if (irparams.rcvstate != STATE_STOP) { + return ERR; + } +#ifdef DEBUG + Serial.println("Attempting NEC decode"); +#endif + if (decodeNEC(results)) { + return DECODED; + } +#ifdef DEBUG + Serial.println("Attempting Sony decode"); +#endif + if (decodeSony(results)) { + return DECODED; + } +#ifdef DEBUG + Serial.println("Attempting RC5 decode"); +#endif + if (decodeRC5(results)) { + return DECODED; + } +#ifdef DEBUG + Serial.println("Attempting RC6 decode"); +#endif + if (decodeRC6(results)) { + return DECODED; + } + // decodeHash returns a hash on any input. + // Thus, it needs to be last in the list. + // If you add any decodes, add them before this. + if (decodeHash(results)) { + return DECODED; + } + // Throw away and start over + resume(); + return ERR; +} + +long IRrecv::decodeNEC(decode_results *results) { + long data = 0; + int offset = 1; // Skip first space + // Initial mark + if (!MATCH_MARK(results->rawbuf[offset], NEC_HDR_MARK)) { + return ERR; + } + offset++; + // Check for repeat + if (irparams.rawlen == 4 && + MATCH_SPACE(results->rawbuf[offset], NEC_RPT_SPACE) && + MATCH_MARK(results->rawbuf[offset+1], NEC_BIT_MARK)) { + results->bits = 0; + results->value = REPEAT; + results->decode_type = NEC; + return DECODED; + } + if (irparams.rawlen < 2 * NEC_BITS + 4) { + return ERR; + } + // Initial space + if (!MATCH_SPACE(results->rawbuf[offset], NEC_HDR_SPACE)) { + return ERR; + } + offset++; + for (int i = 0; i < NEC_BITS; i++) { + if (!MATCH_MARK(results->rawbuf[offset], NEC_BIT_MARK)) { + return ERR; + } + offset++; + if (MATCH_SPACE(results->rawbuf[offset], NEC_ONE_SPACE)) { + data = (data << 1) | 1; + } + else if (MATCH_SPACE(results->rawbuf[offset], NEC_ZERO_SPACE)) { + data <<= 1; + } + else { + return ERR; + } + offset++; + } + // Success + results->bits = NEC_BITS; + results->value = data; + results->decode_type = NEC; + return DECODED; +} + +long IRrecv::decodeSony(decode_results *results) { + long data = 0; + if (irparams.rawlen < 2 * SONY_BITS + 2) { + return ERR; + } + int offset = 1; // Skip first space + // Initial mark + if (!MATCH_MARK(results->rawbuf[offset], SONY_HDR_MARK)) { + return ERR; + } + offset++; + + while (offset + 1 < irparams.rawlen) { + if (!MATCH_SPACE(results->rawbuf[offset], SONY_HDR_SPACE)) { + break; + } + offset++; + if (MATCH_MARK(results->rawbuf[offset], SONY_ONE_MARK)) { + data = (data << 1) | 1; + } + else if (MATCH_MARK(results->rawbuf[offset], SONY_ZERO_MARK)) { + data <<= 1; + } + else { + return ERR; + } + offset++; + } + + // Success + results->bits = (offset - 1) / 2; + if (results->bits < 12) { + results->bits = 0; + return ERR; + } + results->value = data; + results->decode_type = SONY; + return DECODED; +} + +// 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 -1 for error (measured time interval is not a multiple of t1). +int IRrecv::getRClevel(decode_results *results, int *offset, int *used, int t1) { + if (*offset >= results->rawlen) { + // After end of recorded buffer, assume SPACE. + return SPACE; + } + int width = results->rawbuf[*offset]; + int val = ((*offset) % 2) ? MARK : 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 -1; + } + + (*used)++; + if (*used >= avail) { + *used = 0; + (*offset)++; + } +#ifdef DEBUG + if (val == MARK) { + Serial.println("MARK"); + } + else { + Serial.println("SPACE"); + } +#endif + return val; +} + +long IRrecv::decodeRC5(decode_results *results) { + if (irparams.rawlen < MIN_RC5_SAMPLES + 2) { + return ERR; + } + int offset = 1; // Skip gap space + long data = 0; + int used = 0; + // Get start bits + if (getRClevel(results, &offset, &used, RC5_T1) != MARK) return ERR; + if (getRClevel(results, &offset, &used, RC5_T1) != SPACE) return ERR; + if (getRClevel(results, &offset, &used, RC5_T1) != MARK) return ERR; + int nbits; + for (nbits = 0; offset < irparams.rawlen; nbits++) { + int levelA = getRClevel(results, &offset, &used, RC5_T1); + int levelB = getRClevel(results, &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 ERR; + } + } + + // Success + results->bits = nbits; + results->value = data; + results->decode_type = RC5; + return DECODED; +} + +long IRrecv::decodeRC6(decode_results *results) { + if (results->rawlen < MIN_RC6_SAMPLES) { + return ERR; + } + int offset = 1; // Skip first space + // Initial mark + if (!MATCH_MARK(results->rawbuf[offset], RC6_HDR_MARK)) { + return ERR; + } + offset++; + if (!MATCH_SPACE(results->rawbuf[offset], RC6_HDR_SPACE)) { + return ERR; + } + offset++; + long data = 0; + int used = 0; + // Get start bit (1) + if (getRClevel(results, &offset, &used, RC6_T1) != MARK) return ERR; + if (getRClevel(results, &offset, &used, RC6_T1) != SPACE) return ERR; + int nbits; + for (nbits = 0; offset < results->rawlen; nbits++) { + int levelA, levelB; // Next two levels + levelA = getRClevel(results, &offset, &used, RC6_T1); + if (nbits == 3) { + // T bit is double wide; make sure second half matches + if (levelA != getRClevel(results, &offset, &used, RC6_T1)) return ERR; + } + levelB = getRClevel(results, &offset, &used, RC6_T1); + if (nbits == 3) { + // T bit is double wide; make sure second half matches + if (levelB != getRClevel(results, &offset, &used, RC6_T1)) return ERR; + } + 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 ERR; // Error + } + } + // Success + results->bits = nbits; + results->value = data; + results->decode_type = RC6; + return DECODED; +} + +/* ----------------------------------------------------------------------- + * hashdecode - 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. + * + * The algorithm: look at the sequence of MARK signals, and see if each one + * is shorter (0), the same length (1), or longer (2) than the previous. + * Do the same with the SPACE signals. Hszh the resulting sequence of 0's, + * 1's, and 2's to a 32-bit value. This will give a unique value for each + * different code (probably), for most code systems. + * + * http://arcfn.com/2010/01/using-arbitrary-remotes-with-arduino.html + */ + +// Compare two tick values, returning 0 if newval is shorter, +// 1 if newval is equal, and 2 if newval is longer +// Use a tolerance of 20% +int IRrecv::compare(unsigned int oldval, unsigned int newval) { + if (newval < oldval * .8) { + return 0; + } + else if (oldval < newval * .8) { + return 2; + } + else { + return 1; + } +} + +// Use FNV hash algorithm: http://isthe.com/chongo/tech/comp/fnv/#FNV-param +#define FNV_PRIME_32 16777619 +#define FNV_BASIS_32 2166136261 + +/* Converts the raw code values into a 32-bit hash code. + * Hopefully this code is unique for each button. + * This isn't a "real" decoding, just an arbitrary value. + */ +long IRrecv::decodeHash(decode_results *results) { + // Require at least 6 samples to prevent triggering on noise + if (results->rawlen < 6) { + return ERR; + } + long hash = FNV_BASIS_32; + for (int i = 1; i+2 < results->rawlen; i++) { + int value = compare(results->rawbuf[i], results->rawbuf[i+2]); + // Add value into the hash + hash = (hash * FNV_PRIME_32) ^ value; + } + results->value = hash; + results->bits = 32; + results->decode_type = UNKNOWN; + return DECODED; +} + +/* Sharp and DISH support by Todd Treece ( http://unionbridge.org/design/ircommand ) + +The Dish send function needs to be repeated 4 times, and the Sharp function +has the necessary repeat built in because of the need to invert the signal. + +Sharp protocol documentation: +http://www.sbprojects.com/knowledge/ir/sharp.htm + +Here are the LIRC files that I found that seem to match the remote codes +from the oscilloscope: + +Sharp LCD TV: +http://lirc.sourceforge.net/remotes/sharp/GA538WJSA + +DISH NETWORK (echostar 301): +http://lirc.sourceforge.net/remotes/echostar/301_501_3100_5100_58xx_59xx + +For the DISH codes, only send the last for characters of the hex. +i.e. use 0x1C10 instead of 0x0000000000001C10 which is listed in the +linked LIRC file. +*/ + +void IRsend::sendSharp(unsigned long data, int nbits) { + unsigned long invertdata = data ^ SHARP_TOGGLE_MASK; + enableIROut(38); + for (int i = 0; i < nbits; i++) { + if (data & 0x4000) { + mark(SHARP_BIT_MARK); + space(SHARP_ONE_SPACE); + } + else { + mark(SHARP_BIT_MARK); + space(SHARP_ZERO_SPACE); + } + data <<= 1; + } + + mark(SHARP_BIT_MARK); + space(SHARP_ZERO_SPACE); + delay(46); + for (int i = 0; i < nbits; i++) { + if (invertdata & 0x4000) { + mark(SHARP_BIT_MARK); + space(SHARP_ONE_SPACE); + } + else { + mark(SHARP_BIT_MARK); + space(SHARP_ZERO_SPACE); + } + invertdata <<= 1; + } + mark(SHARP_BIT_MARK); + space(SHARP_ZERO_SPACE); + delay(46); +} + +void IRsend::sendDISH(unsigned long data, int nbits) +{ + enableIROut(56); + mark(DISH_HDR_MARK); + space(DISH_HDR_SPACE); + for (int i = 0; i < nbits; i++) { + if (data & DISH_TOP_BIT) { + mark(DISH_BIT_MARK); + space(DISH_ONE_SPACE); + } + else { + mark(DISH_BIT_MARK); + space(DISH_ZERO_SPACE); + } + data <<= 1; + } +} diff --git a/2011-firefly-mega-ssc32/firmware/2012-library/hexapod/IRremote.h b/2011-firefly-mega-ssc32/firmware/2012-library/hexapod/IRremote.h index ef98ceb..9bb514a 100644 --- a/2011-firefly-mega-ssc32/firmware/2012-library/hexapod/IRremote.h +++ b/2011-firefly-mega-ssc32/firmware/2012-library/hexapod/IRremote.h @@ -1,101 +1,101 @@ -/* - * 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 IRremote_h -#define IRremote_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. -// 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. -// #define DEBUG -// #define TEST - -// Results returned from the decoder -class decode_results { -public: - int decode_type; // NEC, SONY, RC5, UNKNOWN - unsigned long value; // Decoded value - int bits; // Number of bits in decoded value - volatile unsigned int *rawbuf; // Raw intervals in .5 us ticks - int rawlen; // Number of records in rawbuf. -}; - -// Values for decode_type -#define NEC 1 -#define SONY 2 -#define RC5 3 -#define RC6 4 -#define DISH 5 -#define SHARP 6 -#define UNKNOWN -1 - -// Decoded value for NEC when a repeat code is received -#define REPEAT 0xffffffff - -// main class for receiving IR -class IRrecv -{ -public: - IRrecv(int recvpin); - void blink13(int blinkflag); - int decode(decode_results *results); - void enableIRIn(); - void resume(); -private: - // These are called by decode - int getRClevel(decode_results *results, int *offset, int *used, int t1); - long decodeNEC(decode_results *results); - long decodeSony(decode_results *results); - long decodeRC5(decode_results *results); - long decodeRC6(decode_results *results); - long decodeHash(decode_results *results); - int compare(unsigned int oldval, unsigned int newval); - -} -; - -// Only used for testing; can remove virtual for shorter code -#ifdef TEST -#define VIRTUAL virtual -#else -#define VIRTUAL -#endif - -class IRsend -{ -public: - IRsend() {} - void sendNEC(unsigned long data, int nbits); - void sendSony(unsigned long data, int nbits); - void sendRaw(unsigned int buf[], int len, int hz); - void sendRC5(unsigned long data, int nbits); - void sendRC6(unsigned long data, int nbits); - void sendDISH(unsigned long data, int nbits); - void sendSharp(unsigned long data, int nbits); - // private: - void enableIROut(int khz); - VIRTUAL void mark(int usec); - VIRTUAL void space(int usec); -} -; - -// Some useful constants - -#define USECPERTICK 50 // microseconds per clock interrupt tick -#define RAWBUF 76 // Length of raw duration buffer - -// Marks tend to be 100us too long, and spaces 100us too short -// when received due to sensor lag. -#define MARK_EXCESS 100 - -#endif +/* + * 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 IRremote_h +#define IRremote_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. +// 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. +// #define DEBUG +// #define TEST + +// Results returned from the decoder +class decode_results { +public: + int decode_type; // NEC, SONY, RC5, UNKNOWN + unsigned long value; // Decoded value + int bits; // Number of bits in decoded value + volatile unsigned int *rawbuf; // Raw intervals in .5 us ticks + int rawlen; // Number of records in rawbuf. +}; + +// Values for decode_type +#define NEC 1 +#define SONY 2 +#define RC5 3 +#define RC6 4 +#define DISH 5 +#define SHARP 6 +#define UNKNOWN -1 + +// Decoded value for NEC when a repeat code is received +#define REPEAT 0xffffffff + +// main class for receiving IR +class IRrecv +{ +public: + IRrecv(int recvpin); + void blink13(int blinkflag); + int decode(decode_results *results); + void enableIRIn(); + void resume(); +private: + // These are called by decode + int getRClevel(decode_results *results, int *offset, int *used, int t1); + long decodeNEC(decode_results *results); + long decodeSony(decode_results *results); + long decodeRC5(decode_results *results); + long decodeRC6(decode_results *results); + long decodeHash(decode_results *results); + int compare(unsigned int oldval, unsigned int newval); + +} +; + +// Only used for testing; can remove virtual for shorter code +#ifdef TEST +#define VIRTUAL virtual +#else +#define VIRTUAL +#endif + +class IRsend +{ +public: + IRsend() {} + void sendNEC(unsigned long data, int nbits); + void sendSony(unsigned long data, int nbits); + void sendRaw(unsigned int buf[], int len, int hz); + void sendRC5(unsigned long data, int nbits); + void sendRC6(unsigned long data, int nbits); + void sendDISH(unsigned long data, int nbits); + void sendSharp(unsigned long data, int nbits); + // private: + void enableIROut(int khz); + VIRTUAL void mark(int usec); + VIRTUAL void space(int usec); +} +; + +// Some useful constants + +#define USECPERTICK 50 // microseconds per clock interrupt tick +#define RAWBUF 76 // Length of raw duration buffer + +// Marks tend to be 100us too long, and spaces 100us too short +// when received due to sensor lag. +#define MARK_EXCESS 100 + +#endif diff --git a/2011-firefly-mega-ssc32/firmware/2012-library/hexapod/IRremoteInt.h b/2011-firefly-mega-ssc32/firmware/2012-library/hexapod/IRremoteInt.h index a0d4b36..14619f2 100644 --- a/2011-firefly-mega-ssc32/firmware/2012-library/hexapod/IRremoteInt.h +++ b/2011-firefly-mega-ssc32/firmware/2012-library/hexapod/IRremoteInt.h @@ -1,398 +1,398 @@ -/* - * IRremote - * Version 0.1 July, 2009 - * Copyright 2009 Ken Shirriff - * For details, see http://arcfn.com/2009/08/multi-protocol-infrared-remote-library.html - * - * Modified by Paul Stoffregen to support other boards and timers - * - * 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 IRremoteint_h -#define IRremoteint_h - -#include - -// define which timer to use -// -// Uncomment the timer you wish to use on your board. If you -// are using another library which uses timer2, you have options -// to switch IRremote to use a different timer. - -// Arduino Mega -#if defined(__AVR_ATmega1280__) - //#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 -#elif defined(__AVR_ATmega32U4__) - //#define IR_USE_TIMER1 // tx = pin 14 - //#define IR_USE_TIMER3 // tx = pin 9 - #define IR_USE_TIMER4_HS // tx = pin 10 - -// 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 - -// Arduino Duemilanove, Diecimila, LilyPad, Mini, Fio, etc -#else - //#define IR_USE_TIMER1 // tx = pin 9 - #define IR_USE_TIMER2 // tx = pin 3 -#endif - - - -#ifdef F_CPU -#define SYSCLOCK F_CPU // main Arduino clock -#else -#define SYSCLOCK 16000000 // main Arduino clock -#endif - -#define ERR 0 -#define DECODED 1 - - -// 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 - - -// pulse parameters in usec -#define NEC_HDR_MARK 9000 -#define NEC_HDR_SPACE 4500 -#define NEC_BIT_MARK 560 -#define NEC_ONE_SPACE 1600 -#define NEC_ZERO_SPACE 560 -#define NEC_RPT_SPACE 2250 - -#define SONY_HDR_MARK 2400 -#define SONY_HDR_SPACE 600 -#define SONY_ONE_MARK 1200 -#define SONY_ZERO_MARK 600 -#define SONY_RPT_LENGTH 45000 - -#define RC5_T1 889 -#define RC5_RPT_LENGTH 46000 - -#define RC6_HDR_MARK 2666 -#define RC6_HDR_SPACE 889 -#define RC6_T1 444 -#define RC6_RPT_LENGTH 46000 - -#define SHARP_BIT_MARK 245 -#define SHARP_ONE_SPACE 1805 -#define SHARP_ZERO_SPACE 795 -#define SHARP_GAP 600000 -#define SHARP_TOGGLE_MASK 0x3FF -#define SHARP_RPT_SPACE 3000 - -#define DISH_HDR_MARK 400 -#define DISH_HDR_SPACE 6100 -#define DISH_BIT_MARK 400 -#define DISH_ONE_SPACE 1700 -#define DISH_ZERO_SPACE 2800 -#define DISH_RPT_SPACE 6200 -#define DISH_TOP_BIT 0x8000 - -#define SHARP_BITS 15 -#define DISH_BITS 16 - -#define TOLERANCE 25 // percent tolerance in measurements -#define LTOL (1.0 - TOLERANCE/100.) -#define UTOL (1.0 + TOLERANCE/100.) - -#define _GAP 5000 // Minimum map between transmissions -#define GAP_TICKS (_GAP/USECPERTICK) - -#define TICKS_LOW(us) (int) (((us)*LTOL/USECPERTICK)) -#define TICKS_HIGH(us) (int) (((us)*UTOL/USECPERTICK + 1)) - -#ifndef DEBUG -#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) -// Debugging versions are in IRremote.cpp -#endif - -// receiver states -#define STATE_IDLE 2 -#define STATE_MARK 3 -#define STATE_SPACE 4 -#define STATE_STOP 5 - -// information for the interrupt handler -typedef struct { - uint8_t recvpin; // pin for IR data from detector - uint8_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; - -// Defined in IRremote.cpp -extern volatile irparams_t irparams; - -// IR detector output is active low -#define MARK 0 -#define SPACE 1 - -#define TOPBIT 0x80000000 - -#define NEC_BITS 32 -#define SONY_BITS 12 -#define MIN_RC5_SAMPLES 11 -#define MIN_RC6_SAMPLES 1 - - - - -// defines for timer2 (8 bits) -#if 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__) -#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__) -#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__) -#define TIMER_PWM_PIN 5 /* Arduino Mega */ -#else -#error "Please add OC3A pin number here\n" -#endif - - -// defines for timer4 (10 bits, high speed option) -#elif defined(IR_USE_TIMER4_HS) -#define TIMER_RESET -#define TIMER_ENABLE_PWM (TCCR4A |= _BV(COM4A1)) -#define TIMER_DISABLE_PWM (TCCR4A &= ~(_BV(COM4A1))) -#define TIMER_ENABLE_INTR (TIMSK4 = _BV(TOIE4)) -#define TIMER_DISABLE_INTR (TIMSK4 = 0) -#define TIMER_INTR_NAME TIMER4_OVF_vect -#define TIMER_CONFIG_KHZ(val) ({ \ - const uint16_t pwmval = SYSCLOCK / 2000 / (val); \ - TCCR4A = (1<> 8; \ - OCR4C = pwmval; \ - TC4H = (pwmval / 3) >> 8; \ - OCR4A = (pwmval / 3) & 255; \ -}) -#define TIMER_CONFIG_NORMAL() ({ \ - TCCR4A = 0; \ - TCCR4B = _BV(CS40); \ - TCCR4C = 0; \ - TCCR4D = 0; \ - TCCR4E = 0; \ - TC4H = (SYSCLOCK * USECPERTICK / 1000000) >> 8; \ - OCR4C = (SYSCLOCK * USECPERTICK / 1000000) & 255; \ - TC4H = 0; \ - TCNT4 = 0; \ -}) -#if defined(CORE_OC4A_PIN) -#define TIMER_PWM_PIN CORE_OC4A_PIN /* Teensy */ -#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__) -#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__) -#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__) -#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) -#else -#define BLINKLED 13 -#define BLINKLED_ON() (PORTB |= B00100000) -#define BLINKLED_OFF() (PORTB &= B11011111) -#endif - -#endif +/* + * IRremote + * Version 0.1 July, 2009 + * Copyright 2009 Ken Shirriff + * For details, see http://arcfn.com/2009/08/multi-protocol-infrared-remote-library.html + * + * Modified by Paul Stoffregen to support other boards and timers + * + * 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 IRremoteint_h +#define IRremoteint_h + +#include + +// define which timer to use +// +// Uncomment the timer you wish to use on your board. If you +// are using another library which uses timer2, you have options +// to switch IRremote to use a different timer. + +// Arduino Mega +#if defined(__AVR_ATmega1280__) + //#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 +#elif defined(__AVR_ATmega32U4__) + //#define IR_USE_TIMER1 // tx = pin 14 + //#define IR_USE_TIMER3 // tx = pin 9 + #define IR_USE_TIMER4_HS // tx = pin 10 + +// 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 + +// Arduino Duemilanove, Diecimila, LilyPad, Mini, Fio, etc +#else + //#define IR_USE_TIMER1 // tx = pin 9 + #define IR_USE_TIMER2 // tx = pin 3 +#endif + + + +#ifdef F_CPU +#define SYSCLOCK F_CPU // main Arduino clock +#else +#define SYSCLOCK 16000000 // main Arduino clock +#endif + +#define ERR 0 +#define DECODED 1 + + +// 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 + + +// pulse parameters in usec +#define NEC_HDR_MARK 9000 +#define NEC_HDR_SPACE 4500 +#define NEC_BIT_MARK 560 +#define NEC_ONE_SPACE 1600 +#define NEC_ZERO_SPACE 560 +#define NEC_RPT_SPACE 2250 + +#define SONY_HDR_MARK 2400 +#define SONY_HDR_SPACE 600 +#define SONY_ONE_MARK 1200 +#define SONY_ZERO_MARK 600 +#define SONY_RPT_LENGTH 45000 + +#define RC5_T1 889 +#define RC5_RPT_LENGTH 46000 + +#define RC6_HDR_MARK 2666 +#define RC6_HDR_SPACE 889 +#define RC6_T1 444 +#define RC6_RPT_LENGTH 46000 + +#define SHARP_BIT_MARK 245 +#define SHARP_ONE_SPACE 1805 +#define SHARP_ZERO_SPACE 795 +#define SHARP_GAP 600000 +#define SHARP_TOGGLE_MASK 0x3FF +#define SHARP_RPT_SPACE 3000 + +#define DISH_HDR_MARK 400 +#define DISH_HDR_SPACE 6100 +#define DISH_BIT_MARK 400 +#define DISH_ONE_SPACE 1700 +#define DISH_ZERO_SPACE 2800 +#define DISH_RPT_SPACE 6200 +#define DISH_TOP_BIT 0x8000 + +#define SHARP_BITS 15 +#define DISH_BITS 16 + +#define TOLERANCE 25 // percent tolerance in measurements +#define LTOL (1.0 - TOLERANCE/100.) +#define UTOL (1.0 + TOLERANCE/100.) + +#define _GAP 5000 // Minimum map between transmissions +#define GAP_TICKS (_GAP/USECPERTICK) + +#define TICKS_LOW(us) (int) (((us)*LTOL/USECPERTICK)) +#define TICKS_HIGH(us) (int) (((us)*UTOL/USECPERTICK + 1)) + +#ifndef DEBUG +#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) +// Debugging versions are in IRremote.cpp +#endif + +// receiver states +#define STATE_IDLE 2 +#define STATE_MARK 3 +#define STATE_SPACE 4 +#define STATE_STOP 5 + +// information for the interrupt handler +typedef struct { + uint8_t recvpin; // pin for IR data from detector + uint8_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; + +// Defined in IRremote.cpp +extern volatile irparams_t irparams; + +// IR detector output is active low +#define MARK 0 +#define SPACE 1 + +#define TOPBIT 0x80000000 + +#define NEC_BITS 32 +#define SONY_BITS 12 +#define MIN_RC5_SAMPLES 11 +#define MIN_RC6_SAMPLES 1 + + + + +// defines for timer2 (8 bits) +#if 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__) +#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__) +#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__) +#define TIMER_PWM_PIN 5 /* Arduino Mega */ +#else +#error "Please add OC3A pin number here\n" +#endif + + +// defines for timer4 (10 bits, high speed option) +#elif defined(IR_USE_TIMER4_HS) +#define TIMER_RESET +#define TIMER_ENABLE_PWM (TCCR4A |= _BV(COM4A1)) +#define TIMER_DISABLE_PWM (TCCR4A &= ~(_BV(COM4A1))) +#define TIMER_ENABLE_INTR (TIMSK4 = _BV(TOIE4)) +#define TIMER_DISABLE_INTR (TIMSK4 = 0) +#define TIMER_INTR_NAME TIMER4_OVF_vect +#define TIMER_CONFIG_KHZ(val) ({ \ + const uint16_t pwmval = SYSCLOCK / 2000 / (val); \ + TCCR4A = (1<> 8; \ + OCR4C = pwmval; \ + TC4H = (pwmval / 3) >> 8; \ + OCR4A = (pwmval / 3) & 255; \ +}) +#define TIMER_CONFIG_NORMAL() ({ \ + TCCR4A = 0; \ + TCCR4B = _BV(CS40); \ + TCCR4C = 0; \ + TCCR4D = 0; \ + TCCR4E = 0; \ + TC4H = (SYSCLOCK * USECPERTICK / 1000000) >> 8; \ + OCR4C = (SYSCLOCK * USECPERTICK / 1000000) & 255; \ + TC4H = 0; \ + TCNT4 = 0; \ +}) +#if defined(CORE_OC4A_PIN) +#define TIMER_PWM_PIN CORE_OC4A_PIN /* Teensy */ +#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__) +#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__) +#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__) +#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) +#else +#define BLINKLED 13 +#define BLINKLED_ON() (PORTB |= B00100000) +#define BLINKLED_OFF() (PORTB &= B11011111) +#endif + +#endif diff --git a/2011-firefly-mega-ssc32/firmware/2012-library/hexapod/InverseKinemetics.cpp b/2011-firefly-mega-ssc32/firmware/2012-library/hexapod/InverseKinemetics.cpp index fda2b6b..ca0708a 100644 --- a/2011-firefly-mega-ssc32/firmware/2012-library/hexapod/InverseKinemetics.cpp +++ b/2011-firefly-mega-ssc32/firmware/2012-library/hexapod/InverseKinemetics.cpp @@ -3,6 +3,7 @@ //Variables boolean error; +boolean OOF; // OutOfReach void RL3 (int i, Data *DataLine) { @@ -72,7 +73,7 @@ float T3 (Data *DataLine) void setleg (int i, Data *DataLine) { - Segment Seg; + //Segment Seg; if (i < 3) { @@ -90,8 +91,8 @@ void setleg (int i, Data *DataLine) } else { - error = true; - Seg.sevenSegWrite('e'); + OOF = true; + //Seg.sevenSegWrite('e'); } } else @@ -110,18 +111,19 @@ void setleg (int i, Data *DataLine) } else { - error = true; - Seg.sevenSegWrite('e'); + OOF = true; + //Seg.sevenSegWrite('e'); } } } void InverseKinemetics::IK(Data *DataLine) { - Segment Seg; - Seg.sevenSegWrite('o'); + //Segment Seg; + //Seg.sevenSegWrite('o'); error = false; + OOF = false; for (int i=0; i<6; i++) setleg(i, DataLine); @@ -132,7 +134,7 @@ void InverseKinemetics::IK(Data *DataLine) if (i != 0) Serial.print(", "); else - Serial.print("### InverseKinemetics->ServosPosition's are: "); + Serial.print("### InverseKinemetics->ServoData[" + i + "]: "); Serial.print(DataLine->ServoData[i].x); Serial.print(", "); diff --git a/2011-firefly-mega-ssc32/firmware/2012-library/hexapod/Segment.cpp b/2011-firefly-mega-ssc32/firmware/2012-library/hexapod/Segment.cpp index ac49117..1cbab20 100644 --- a/2011-firefly-mega-ssc32/firmware/2012-library/hexapod/Segment.cpp +++ b/2011-firefly-mega-ssc32/firmware/2012-library/hexapod/Segment.cpp @@ -1,84 +1,84 @@ -// 7Segment -#include "Arduino.h" -#include "Segment.h" - -byte seven_seg_digits[][8] = { - { 0,1,1,1,1,1,0,1 }, // = 0 - { 0,1,1,0,0,0,0,0 }, // = 1 - { 0,0,1,1,1,1,1,0 }, // = 2 - { 0,1,1,1,1,0,1,0 }, // = 3 - { 0,1,1,0,0,0,1,1 }, // = 4 - { 0,1,0,1,1,0,1,1 }, // = 5 - { 0,1,0,1,1,1,1,1 }, // = 6 - { 0,1,1,1,0,0,0,0 }, // = 7 - { 0,1,1,1,1,1,1,1 }, // = 8 - { 0,1,1,1,1,0,1,1 }, // = 9 - { 1,1,1,1,0,1,1,1 }, // = A - { 1,1,0,0,1,1,1,1 }, // = B - { 1,0,0,1,1,1,0,1 }, // = C - { 1,1,0,0,1,1,1,1 }, // = D - { 1,0,0,1,1,1,1,1 }, // = E - { 1,0,0,1,0,1,1,1 }, // = F - { 1,1,0,1,1,0,1,1 }, // = S - { 0,0,0,0,0,0,0,0 }, // = NULL - { 1,0,0,1,0,1,0,1 } // = R -}; - -Segment::Segment() { - for (int i=0; i<8; i++) - pinMode(6+i, OUTPUT); -} - -/*void Segment::sevenSegWrite(byte digit) { - byte pin = 6; - for (byte segCount = 0; segCount < 8; ++segCount) { - digitalWrite(pin, !seven_seg_digits[digit][segCount]); - ++pin; - } -}*/ - -void Segment::sevenSegWrite(char chr) { - byte pin = 6; - byte digit; - if(chr <= 9) digit = chr; - else if (chr <= 'f') digit = 10 + (chr -'a'); - else if (chr == 's') digit = 16; - else if (chr == 'r') digit = 18; - else digit = Cls; - for (byte segCount = 0; segCount < 8; ++segCount) { - digitalWrite(pin, !seven_seg_digits[digit][segCount]); - ++pin; - } -} - -/*void Segment::BlinksevenSegWrite(byte digit) { - byte pin = 6; - for (byte segCount = 0; segCount < 8; ++segCount) { - digitalWrite(pin, !seven_seg_digits[digit][segCount]); - ++pin; - } - delay(100); - sevenSegWrite((byte)17); -}*/ - -void Segment::BlinksevenSegWrite(char chr) { - byte pin = 6; - byte digit; - if(chr <= 9) digit = chr; - else if (chr <= 'f') digit = 10 + (chr -'a'); - else if (chr == 's') digit = 16; - else digit = Cls; - for (byte segCount = 0; segCount < 8; ++segCount) { - digitalWrite(pin, !seven_seg_digits[digit][segCount]); - ++pin; - } - delay(100); - sevenSegWrite(Cls); -} - - - - - - +// 7Segment +#include "Arduino.h" +#include "Segment.h" + +byte seven_seg_digits[][8] = { + { 0,1,1,1,1,1,0,1 }, // = 0 + { 0,1,1,0,0,0,0,0 }, // = 1 + { 0,0,1,1,1,1,1,0 }, // = 2 + { 0,1,1,1,1,0,1,0 }, // = 3 + { 0,1,1,0,0,0,1,1 }, // = 4 + { 0,1,0,1,1,0,1,1 }, // = 5 + { 0,1,0,1,1,1,1,1 }, // = 6 + { 0,1,1,1,0,0,0,0 }, // = 7 + { 0,1,1,1,1,1,1,1 }, // = 8 + { 0,1,1,1,1,0,1,1 }, // = 9 + { 1,1,1,1,0,1,1,1 }, // = A + { 1,1,0,0,1,1,1,1 }, // = B + { 1,0,0,1,1,1,0,1 }, // = C + { 1,1,0,0,1,1,1,1 }, // = D + { 1,0,0,1,1,1,1,1 }, // = E + { 1,0,0,1,0,1,1,1 }, // = F + { 1,1,0,1,1,0,1,1 }, // = S + { 0,0,0,0,0,0,0,0 }, // = NULL + { 1,0,0,1,0,1,0,1 } // = R +}; + +Segment::Segment() { + for (int i=0; i<8; i++) + pinMode(6+i, OUTPUT); +} + +/*void Segment::sevenSegWrite(byte digit) { + byte pin = 6; + for (byte segCount = 0; segCount < 8; ++segCount) { + digitalWrite(pin, !seven_seg_digits[digit][segCount]); + ++pin; + } +}*/ + +void Segment::sevenSegWrite(char chr) { + byte pin = 6; + byte digit; + if(chr <= 9) digit = chr; + else if (chr <= 'f') digit = 10 + (chr -'a'); + else if (chr == 's') digit = 16; + else if (chr == 'r') digit = 18; + else digit = Cls; + for (byte segCount = 0; segCount < 8; ++segCount) { + digitalWrite(pin, !seven_seg_digits[digit][segCount]); + ++pin; + } +} + +/*void Segment::BlinksevenSegWrite(byte digit) { + byte pin = 6; + for (byte segCount = 0; segCount < 8; ++segCount) { + digitalWrite(pin, !seven_seg_digits[digit][segCount]); + ++pin; + } + delay(100); + sevenSegWrite((byte)17); +}*/ + +void Segment::BlinksevenSegWrite(char chr) { + byte pin = 6; + byte digit; + if(chr <= 9) digit = chr; + else if (chr <= 'f') digit = 10 + (chr -'a'); + else if (chr == 's') digit = 16; + else digit = Cls; + for (byte segCount = 0; segCount < 8; ++segCount) { + digitalWrite(pin, !seven_seg_digits[digit][segCount]); + ++pin; + } + delay(100); + sevenSegWrite(Cls); +} + + + + + + diff --git a/2011-firefly-mega-ssc32/firmware/2012-library/hexapod/Segment.h b/2011-firefly-mega-ssc32/firmware/2012-library/hexapod/Segment.h index 1b9aeb4..edbafab 100644 --- a/2011-firefly-mega-ssc32/firmware/2012-library/hexapod/Segment.h +++ b/2011-firefly-mega-ssc32/firmware/2012-library/hexapod/Segment.h @@ -1,20 +1,20 @@ -// 7 Segment driver. - -#ifndef SEGMENT_H -#define SEGMENT_H - -#include "Arduino.h" -#define Cls 17 - -class Segment -{ -public: - Segment(); - //void sevenSegWrite(byte digit); - void sevenSegWrite(char chr); - //void BlinksevenSegWrite(byte digit); - void BlinksevenSegWrite(char chr); -}; - -#endif +// 7 Segment driver. + +#ifndef SEGMENT_H +#define SEGMENT_H + +#include "Arduino.h" +#define Cls 17 + +class Segment +{ +public: + Segment(); + //void sevenSegWrite(byte digit); + void sevenSegWrite(char chr); + //void BlinksevenSegWrite(byte digit); + void BlinksevenSegWrite(char chr); +}; + +#endif diff --git a/2011-firefly-mega-ssc32/firmware/2012-library/hexapod/TinyGPS.h b/2011-firefly-mega-ssc32/firmware/2012-library/hexapod/TinyGPS.h index 22fa80c..d906792 100644 --- a/2011-firefly-mega-ssc32/firmware/2012-library/hexapod/TinyGPS.h +++ b/2011-firefly-mega-ssc32/firmware/2012-library/hexapod/TinyGPS.h @@ -23,7 +23,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #ifndef TinyGPS_h #define TinyGPS_h -#if defined(ARDUINO) && ARDUINO >= 100 +#if defined(ARDUINO) && ARDUINO >= 100 #include "Arduino.h" #else #include "WProgram.h" diff --git a/2011-firefly-mega-ssc32/firmware/2012-library/hexapod/WiiChuck.h b/2011-firefly-mega-ssc32/firmware/2012-library/hexapod/WiiChuck.h index bac0467..760d119 100644 --- a/2011-firefly-mega-ssc32/firmware/2012-library/hexapod/WiiChuck.h +++ b/2011-firefly-mega-ssc32/firmware/2012-library/hexapod/WiiChuck.h @@ -1,190 +1,190 @@ -#ifndef WiiChuck_h -#define WiiChuck_h - -#include "Arduino.h" -#include "Wire.h" -#include "math.h" - - -// these may need to be adjusted for each nunchuck for calibration -#define ZEROX 510 -#define ZEROY 490 -#define ZEROZ 460 -#define RADIUS 210 // probably pretty universal - -#define DEFAULT_ZERO_JOY_X 124 -#define DEFAULT_ZERO_JOY_Y 132 - -#define MAXANGLE 90 -#define MINANGLE -90 - -class WiiChuck { -private: - byte cnt; - uint8_t status[6]; // array to store wiichuck output - byte averageCounter; - int i; - int total; - uint8_t zeroJoyX; // these are about where mine are - uint8_t zeroJoyY; // use calibrateJoy when the stick is at zero to correct - int lastJoyX; - int lastJoyY; - int angles[3]; - - boolean lastZ, lastC; - - -public: - - byte joyX; - byte joyY; - boolean buttonZ; - boolean buttonC; - boolean plugd; - void begin() - { - Wire.begin(); - cnt = 0; - averageCounter = 0; - Wire.beginTransmission (0x52); // transmit to device 0x52 - Wire.write((byte)0x40); // sends memory address - Wire.write((byte)0x00); // sends memory address - Wire.endTransmission (); // stop transmitting - update(); - for (i = 0; i<3;i++) { - angles[i] = 0; - } - zeroJoyX = DEFAULT_ZERO_JOY_X; - zeroJoyY = DEFAULT_ZERO_JOY_Y; - } - - - void calibrateJoy() { - zeroJoyX = joyX; - zeroJoyY = joyY; - } - - void CheckifPlugd() - { - if (this->plugd == false){ - this->begin(); - -#ifdef GLCD - GLCD.CursorTo(1, 1); - GLCD.print("No Chuck"); - delay(100); -#endif - - this->begin(); - if (this->plugd) - this->calibrateJoy(); - } - } - - void update() { - - Wire.requestFrom (0x52, 6); // request data from nunchuck - while (Wire.available ()) { - // receive byte as an integer - status[cnt] = _nunchuk_decode_byte((byte)Wire.read()); // - cnt++; - } - if (cnt > 5) { - lastZ = buttonZ; - lastC = buttonC; - lastJoyX = readJoyX(); - lastJoyY = readJoyY(); - - cnt = 0; - joyX = (status[0]); - joyY = (status[1]); - for (i = 0; i < 3; i++) - angles[i] = (status[i+2] << 2) + ((status[5] & (B00000011 << ((i+1)*2) ) >> ((i+1)*2))); - - buttonZ = !( status[5] & B00000001); - buttonC = !((status[5] & B00000010) >> 1); - _send_zero(); // send the request for next bytes - plugd = true; - } - else if (cnt == 0) - plugd = false; - } - - float readAccelX() { - return (float)angles[0] - ZEROX; - } - float readAccelY() { - return (float)angles[1] - ZEROY; - } - float readAccelZ() { - return (float)angles[2] - ZEROZ; - } - - boolean zPressed() { - return (buttonZ && ! lastZ); - } - boolean cPressed() { - return (buttonC && ! lastC); - } - - // for using the joystick like a directional button - boolean rightJoy(int thresh=60) { - return (readJoyX() > thresh and lastJoyX <= thresh); - } - - // for using the joystick like a directional button - boolean leftJoy(int thresh=60) { - return (readJoyX() < -thresh and lastJoyX >= -thresh); - } - - - int readJoyX() { - return (int) joyX - zeroJoyX; - } - - int readJoyY() { - return (int)joyY - zeroJoyY; - } - - - // R, the radius, generally hovers around 210 (at least it does with mine) - int R() { - return sqrt(readAccelX() * readAccelX() +readAccelY() * readAccelY() + readAccelZ() * readAccelZ()); - } - - - // returns roll degrees - int readRoll() { - return (int)(atan2(readAccelX(),readAccelZ())/ M_PI * 180.0); - } - - // returns pitch in degrees - int readPitch() { - return (int) (acos(readAccelY()/RADIUS)/ M_PI * 180.0); // optionally swap 'RADIUS' for 'R()' - } - -private: - byte _nunchuk_decode_byte (byte x) - { - x = (x ^ 0x17) + 0x17; - return x; - } - - void _send_zero() - { - Wire.beginTransmission (0x52); // transmit to device 0x52 - Wire.write ((byte)0x00); // sends one byte - Wire.endTransmission (); // stop transmitting - } - -}; - - -#endif - - - - - - +#ifndef WiiChuck_h +#define WiiChuck_h + +#include "Arduino.h" +#include "Wire.h" +#include "math.h" + + +// these may need to be adjusted for each nunchuck for calibration +#define ZEROX 510 +#define ZEROY 490 +#define ZEROZ 460 +#define RADIUS 210 // probably pretty universal + +#define DEFAULT_ZERO_JOY_X 124 +#define DEFAULT_ZERO_JOY_Y 132 + +#define MAXANGLE 90 +#define MINANGLE -90 + +class WiiChuck { +private: + byte cnt; + uint8_t status[6]; // array to store wiichuck output + byte averageCounter; + int i; + int total; + uint8_t zeroJoyX; // these are about where mine are + uint8_t zeroJoyY; // use calibrateJoy when the stick is at zero to correct + int lastJoyX; + int lastJoyY; + int angles[3]; + + boolean lastZ, lastC; + + +public: + + byte joyX; + byte joyY; + boolean buttonZ; + boolean buttonC; + boolean plugd; + void begin() + { + Wire.begin(); + cnt = 0; + averageCounter = 0; + Wire.beginTransmission (0x52); // transmit to device 0x52 + Wire.write((byte)0x40); // sends memory address + Wire.write((byte)0x00); // sends memory address + Wire.endTransmission (); // stop transmitting + update(); + for (i = 0; i<3;i++) { + angles[i] = 0; + } + zeroJoyX = DEFAULT_ZERO_JOY_X; + zeroJoyY = DEFAULT_ZERO_JOY_Y; + } + + + void calibrateJoy() { + zeroJoyX = joyX; + zeroJoyY = joyY; + } + + void CheckifPlugd() + { + if (this->plugd == false){ + this->begin(); + +#ifdef GLCD + GLCD.CursorTo(1, 1); + GLCD.print("No Chuck"); + delay(100); +#endif + + this->begin(); + if (this->plugd) + this->calibrateJoy(); + } + } + + void update() { + + Wire.requestFrom (0x52, 6); // request data from nunchuck + while (Wire.available ()) { + // receive byte as an integer + status[cnt] = _nunchuk_decode_byte((byte)Wire.read()); // + cnt++; + } + if (cnt > 5) { + lastZ = buttonZ; + lastC = buttonC; + lastJoyX = readJoyX(); + lastJoyY = readJoyY(); + + cnt = 0; + joyX = (status[0]); + joyY = (status[1]); + for (i = 0; i < 3; i++) + angles[i] = (status[i+2] << 2) + ((status[5] & (B00000011 << ((i+1)*2) ) >> ((i+1)*2))); + + buttonZ = !( status[5] & B00000001); + buttonC = !((status[5] & B00000010) >> 1); + _send_zero(); // send the request for next bytes + plugd = true; + } + else if (cnt == 0) + plugd = false; + } + + float readAccelX() { + return (float)angles[0] - ZEROX; + } + float readAccelY() { + return (float)angles[1] - ZEROY; + } + float readAccelZ() { + return (float)angles[2] - ZEROZ; + } + + boolean zPressed() { + return (buttonZ && ! lastZ); + } + boolean cPressed() { + return (buttonC && ! lastC); + } + + // for using the joystick like a directional button + boolean rightJoy(int thresh=60) { + return (readJoyX() > thresh and lastJoyX <= thresh); + } + + // for using the joystick like a directional button + boolean leftJoy(int thresh=60) { + return (readJoyX() < -thresh and lastJoyX >= -thresh); + } + + + int readJoyX() { + return (int) joyX - zeroJoyX; + } + + int readJoyY() { + return (int)joyY - zeroJoyY; + } + + + // R, the radius, generally hovers around 210 (at least it does with mine) + int R() { + return sqrt(readAccelX() * readAccelX() +readAccelY() * readAccelY() + readAccelZ() * readAccelZ()); + } + + + // returns roll degrees + int readRoll() { + return (int)(atan2(readAccelX(),readAccelZ())/ M_PI * 180.0); + } + + // returns pitch in degrees + int readPitch() { + return (int) (acos(readAccelY()/RADIUS)/ M_PI * 180.0); // optionally swap 'RADIUS' for 'R()' + } + +private: + byte _nunchuk_decode_byte (byte x) + { + x = (x ^ 0x17) + 0x17; + return x; + } + + void _send_zero() + { + Wire.beginTransmission (0x52); // transmit to device 0x52 + Wire.write ((byte)0x00); // sends one byte + Wire.endTransmission (); // stop transmitting + } + +}; + + +#endif + + + + + + diff --git a/2011-firefly-mega-ssc32/firmware/2012-library/hexapod/concept_informatie.txt b/2011-firefly-mega-ssc32/firmware/2012-library/hexapod/concept_informatie.txt index 74ddcb5..16b7568 100644 --- a/2011-firefly-mega-ssc32/firmware/2012-library/hexapod/concept_informatie.txt +++ b/2011-firefly-mega-ssc32/firmware/2012-library/hexapod/concept_informatie.txt @@ -1,62 +1,62 @@ -class gedrag{ - - private: - - data_line PositieInformatie; - body_struct main_positie; - int HuidigePositieinProgramma; - int matrix[..] MatrixmetdeGedragPatroonen; - - public: - - run() - { - /* - run normaal gedrag patroon. - - [loop patroon dat niet word beinvloed door userinput] - vraag aankomende gedrag op uit matrix, - -bereken de nieuwe posities - --sla deze op in cache - ---wacht tot de watchdog een timeout geeft - ----geef de cache door aan de servo controller. - - [loop patroon dat WORD beinvloed door userinput] - vraag aankomende gedrag op uit matrix met userinput, - -bereken de nieuwe posities - --sla deze op in cache - ---loop tot de watchdog een timeout geeft - ----geef de cache door aan de servo controller. - */ - }; - - quite() - { - while() - { - /* - maak routine af om terug te gaan naar de main positie. - daarna return 0; - - verplaats de body in een neutrale positie - +als niet mogeleijk verplaats de poten die problemen geven - -mogelijk ga verder met de poten een voor een in de goode positie te zetten - */ - } - }; - - exit() - { - /* - NOOD, stop nu en return positie; - */ - }; - - userinput() - { - /* - Mogelijkheid tot user input. - */ - }; - +class gedrag{ + + private: + + data_line PositieInformatie; + body_struct main_positie; + int HuidigePositieinProgramma; + int matrix[..] MatrixmetdeGedragPatroonen; + + public: + + run() + { + /* + run normaal gedrag patroon. + + [loop patroon dat niet word beinvloed door userinput] + vraag aankomende gedrag op uit matrix, + -bereken de nieuwe posities + --sla deze op in cache + ---wacht tot de watchdog een timeout geeft + ----geef de cache door aan de servo controller. + + [loop patroon dat WORD beinvloed door userinput] + vraag aankomende gedrag op uit matrix met userinput, + -bereken de nieuwe posities + --sla deze op in cache + ---loop tot de watchdog een timeout geeft + ----geef de cache door aan de servo controller. + */ + }; + + quite() + { + while() + { + /* + maak routine af om terug te gaan naar de main positie. + daarna return 0; + + verplaats de body in een neutrale positie + +als niet mogeleijk verplaats de poten die problemen geven + -mogelijk ga verder met de poten een voor een in de goode positie te zetten + */ + } + }; + + exit() + { + /* + NOOD, stop nu en return positie; + */ + }; + + userinput() + { + /* + Mogelijkheid tot user input. + */ + }; + }; diff --git a/2011-firefly-mega-ssc32/firmware/2012-library/hexapod/hexapod.h b/2011-firefly-mega-ssc32/firmware/2012-library/hexapod/hexapod.h index 12c12ee..40450ea 100644 --- a/2011-firefly-mega-ssc32/firmware/2012-library/hexapod/hexapod.h +++ b/2011-firefly-mega-ssc32/firmware/2012-library/hexapod/hexapod.h @@ -17,7 +17,7 @@ //Addons #include "Segment.h" #include "IRremote.h" -#include "TinyGPS.h" +//#include "TinyGPS.h" //#include "WiiChuck.h" //#include "Wire.h"