led-controller/firmware/ir_nec.c

114 lines
3.4 KiB
C
Raw Normal View History

2013-10-15 13:37:30 +02:00
/* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* This is part of the LED light controller program.
* It handles the IR NEC protocol decoding.
* More information at http://www.sbprojects.com/knowledge/ir/nec.php
*/
2013-10-14 16:47:25 +02:00
#include <stdint.h> /* Standard Integer Types */
#include <stdio.h> /* Standard IO facilities */
#include <stdlib.h> /* General utilities */
#include <stdbool.h> /* Boolean */
#include "ir_nec.h"
const uint16_t MARKS[2]={9000,560};
const uint16_t SPACES[4]={4500,2250,1680,560};
2013-10-14 16:47:25 +02:00
void time2nec(uint16_t* burst, uint8_t pulses)
{
uint8_t i,j;
for (i=0; i<pulses; i++) {
if (0==burst[i]) { /* end of burst */
return;
}
if (0==i%2) { /* mark */
2013-10-26 17:31:04 +02:00
/* fine the nearest NEC mark time */
2013-10-14 16:47:25 +02:00
bool found = false;
for (j=0; j<(sizeof(MARKS)/sizeof(uint16_t))-1; j++) {
if (burst[i]>((MARKS[j]+MARKS[j+1])/2)) {
burst[i] = j;
found = true;
break;
}
}
if (!found) {
burst[i] = j;
}
} else { /* space */
2013-10-26 17:31:04 +02:00
/* fine the nearest NEC space time */
2013-10-14 16:47:25 +02:00
bool found = false;
for (j=0; j<(sizeof(SPACES)/sizeof(uint16_t))-1; j++) {
if (burst[i]>((SPACES[j]+SPACES[j+1])/2)) {
burst[i] = j;
found = true;
break;
}
}
if (!found) {
burst[i] = j;
}
}
}
}
struct nec nec2data(uint16_t* burst, uint8_t pulses)
{
struct nec to_return;
to_return.valid = false;
if (67==pulses) { /* normal burst */
to_return.repeat = false;
if (0==burst[0] && 0==burst[1] && 1==burst[pulses-1]) { /* mark start, space start, trailing mark bit */
uint32_t data = 0; /* complete data */
to_return.valid = true;
for (uint8_t i=2; i<pulses-1; i+=2) {
if (1==burst[i] && 2==burst[i+1]) { /* mark bit, space 1 */
data = (data<<1)+1;
} else if (1==burst[i] && 3==burst[i+1]) { /* mark bit, space 0 */
data = (data<<1)+0;
} else {
to_return.valid = false;
}
}
2013-10-26 17:31:04 +02:00
/* decode the valid data into address and command */
2013-10-14 16:47:25 +02:00
if (to_return.valid) {
2013-10-26 17:31:04 +02:00
uint8_t address = (data>>24)&0xff; /* first byte is the address */
uint8_t naddress = (data>>16)&0xff; /* second byte is the inverted address */
uint8_t command = (data>>8)&0xff; /* third byte is the command */
uint8_t ncommand = (data>>0)&0xff; /* fourth byte is the inverted command */
if (0xff==(address^naddress)) { /* check if the data is not corrupted (the address comes also inverted) */
2013-10-14 16:47:25 +02:00
to_return.address = address;
} else {
to_return.valid = false;
}
2013-10-26 17:31:04 +02:00
if (0xff==(command^ncommand)) { /* check if the data is not corrupted (the command comes also inverted) */
2013-10-14 16:47:25 +02:00
to_return.command = command;
} else {
to_return.valid = false;
}
}
}
} else if (3==pulses) { /* repeat burst */
if (0==burst[0] && 1==burst[1] && 1==burst[2]) { /* mark start, space repeat, mark bit */
to_return.valid = true;
to_return.repeat = true;
}
}
return to_return;
}