Hello,
I am very frustrated am i'm still on the project to decode the IR remote of my toy Heli.
Unfortunately I'm stuck and I need your help in the conversion of the code below.
Thanks for this great article!
Sending the Data through serial is a secondary problem, it 's more important for me how to decode the IR Signals
//#define F_CPU 8000000UL
#include <avr/io.h>
#include <avr/interrupt.h>
#define LED_PIN PB0 2
#define SERIAL_PIN PB3 4
#define IR_PIN PB4 11 //tsop31238 DataPin
#define PORT PORTB
#define DDRD DRB
#define PIN PINB
#define TIMER_COUNT TCNT0 // How does it work with the MSP?
// SERIAL SIGNALS
#define BYTE_SIZE = 8
const unsigned long T0 = 500; // in microseconds
const unsigned long T1 = T0 * 3;
const unsigned long START = T0 * 8;
const unsigned long BETWEEN_BITS = T0;
// IR SIGNALS
#define SIGNAL_SIZE 26 // MAX is 29
#define SIGNAL_SPEED 7//from 0 to here
#define SIGNAL_DIR 13//from end of SignalSpeed to here
#define SIGNAL_BUTTONS 17//from end of SignalDir to here
#define SIGNAL_VERTICAL 21//from end of SignalButtons to here
#define SIGNAL_TRIMMER 26//from end of SignalVertical to here
#define PULSE_START_MIN 1500 // in Micro Seconds
#define PULSE_START_MAX 2000
#define PULSE_0_MIN 300
#define PULSE_0_MAX 750
#define PULSE_1_MIN 750
#define PULSE_1_MAX 1200
#define VALUE_LEFT_BUTTON 22
#define VALUE_RIGHT_BUTTON 26
void ledON(){
PORT |= _BV(LED_PIN); // turn on the LED
}
void ledOFF(){
PORT &= ~_BV(LED_PIN); // turn off the LED
}
/* TIMING STUFF */ // How do i set up the correct TimerA0/A1 for MSP430G2533?
void timerConf(){
TCCR0A = 0x00;
TCCR0B = 1 << CS01; // prescaler 8. IF F_CPU is 8MHz then counting directly in uSecs
TIMSK = 1 << TOIE0; //Overflow Interrupt Enabled
//Enable Global Interrupts
sei();
}
// don't forget the VOLATILE, otherwise it will be seen as 0 from the outside !!!
volatile unsigned long _timerOverflow;
ISR(TIMER0_OVF_vect){
_timerOverflow++;
}
void resetTimer(){
TIMER_COUNT = 0; // How to reset Timer on MSP430??
_timerOverflow = 0;
}
unsigned long getTimer(){
return _timerOverflow * 256 + TIMER_COUNT;
}
void delay_us(unsigned long microSecs){
resetTimer();
while(getTimer() < microSecs) {};
}
/* TIMING STUFF - END */
void serialSendStart(){
PORT |= _BV(SERIAL_PIN); // high
delay_us(START);
PORT &= ~_BV(SERIAL_PIN); // low
delay_us(BETWEEN_BITS);
}
void serialSendBits(unsigned char data){
for(unsigned char i = 0; i < 8; i++){
PORT |= _BV(SERIAL_PIN); // high // _BV(xxx) same as: (1 << SERIAL_PIN))
if(data & 0x01) delay_us(T1);
else delay_us(T0);
PORT &= ~_BV(SERIAL_PIN); // low
delay_us(BETWEEN_BITS);
data >>= 1; // get the next most significant bit
}
}
unsigned char irState(){
return PIN & _BV(IR_PIN); // get the value of the IR PIN, 0 or 1
}
static unsigned char getBit(int pulse){
if(pulse > PULSE_0_MIN && pulse < PULSE_0_MAX) return 0;
if(pulse > PULSE_1_MIN && pulse < PULSE_1_MAX) return 1;
return 111; // BAAAD
}
unsigned long _currTimer;
int getIRLowPulse(unsigned int timeoutMicroSecs){
resetTimer();
// wait until it gets LOW or timesout
_currTimer = getTimer();
while(irState() && _currTimer < timeoutMicroSecs) {
_currTimer = getTimer();
}
// time out
if(_currTimer >= timeoutMicroSecs) return -1;
// start conting the pulse
resetTimer();
_currTimer = getTimer();
while(! irState() && _currTimer < timeoutMicroSecs) {
_currTimer = getTimer();
}
// pulse too long
if(_currTimer >= timeoutMicroSecs) return -2;
return _currTimer;
}
int _pulseCount = -1;
unsigned char _bit = 0;
unsigned char _bits[SIGNAL_SIZE];
int _pulse;
unsigned char i = 0;
unsigned char _speed, _dir, _buttons, _vertical, _trimmer;
unsigned char _speedPrev, _dirPrev, _buttonsPrev, _verticalPrev, _trimmerPrev;
void send(){
ledON();
_speed = 0; _dir = 0; _buttons = 0; _vertical = 0; _trimmer = 0;
for(i=0; i<SIGNAL_SIZE; i++){
if (_bits[i] == 1){
if (i < SIGNAL_SPEED) _speed += (1 << (SIGNAL_SPEED - i));
else if (i < SIGNAL_DIR) _dir += (1 << (SIGNAL_DIR - i));
else if (i < SIGNAL_BUTTONS) _buttons += (1 << (SIGNAL_BUTTONS - i));
else if (i < SIGNAL_VERTICAL) _vertical += (1 << (SIGNAL_VERTICAL - i));
else if (i < SIGNAL_TRIMMER) _trimmer += (1 << (SIGNAL_TRIMMER - i));
}
}
if(_buttons == VALUE_LEFT_BUTTON) _buttons = 1;
else if (_buttons == VALUE_RIGHT_BUTTON) _buttons = 2;
else _buttons = 0;
if(_speed != _speedPrev || _dir != _dirPrev || _buttons != _buttonsPrev || _vertical != _verticalPrev || _trimmer != _trimmerPrev){
_speedPrev = _speed; _dirPrev = _dir; _buttonsPrev = _buttons; _verticalPrev = _vertical; _trimmerPrev = _trimmer;
serialSendStart();
serialSendBits(_speed);
serialSendBits(_dir);
serialSendBits(_vertical);
serialSendBits(_trimmer);
serialSendBits(_buttons);
}
ledOFF();
}
void init(){
timerConf();
// make both LED and SERIAL pins outputs
DDR |= _BV(LED_PIN) | _BV(SERIAL_PIN);
// IR_LED is an input
DDR &= ~_BV(IR_PIN);
// SERIAL PORT start LOW
PORT &= ~_BV(SERIAL_PIN);
}
int main(void){
init();
while(1){
_pulse = getIRLowPulse(10000);
if (_pulse > PULSE_START_MIN && _pulse < PULSE_START_MAX){
//start counting pulses
_pulseCount = 0;
}else if (_pulseCount >= 0){ //continue counting pulses
_bit = getBit(_pulse);
// if invalid bit, stop here
if(_bit > 1){
_pulseCount = -1;
}else{
_bits[_pulseCount] = _bit;
// good, wait for next bit
_pulseCount++;
// FINAL, we've read what we wanted let our caller know !
if (_pulseCount == SIGNAL_SIZE) {
send();
// end of this command, so reInit so that we wait for another start
_pulseCount = -1;
}
}
}
}
return 0;
}