IR NEC protocol decoder added

This commit is contained in:
King Kévin 2013-10-14 16:47:25 +02:00
parent 9883e2d8d6
commit a3a1aadd02
5 changed files with 125 additions and 9 deletions

View File

@ -6,7 +6,7 @@ TARGET=led-controller
CC=avr-gcc
OBJDUMP=avr-objdump
OBJCOPY=avr-objcopy
CFLAGS=-g -Werror -O3 -std=c99
CFLAGS=-g -Wall -Werror -O3 -std=c99
# the target
DEVICE=atmega328p
F_CPU=18432000UL
@ -19,7 +19,7 @@ PROGRAMMER=usbtiny
#AVRDUDE=avrdude -p $(DEVICE) -P $(PORT) -c $(PROGRAMMER)
FLASHER=avrdude -p $(DEVICE) -c $(PROGRAMMER)
# source files to compile
SRC = main.c uart.c
SRC = main.c uart.c ir_nec.c
# object files.
OBJ = $(SRC:.c=.o)
# listing files.

88
src/ir_nec.c Normal file
View File

@ -0,0 +1,88 @@
#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"
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 */
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 */
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;
}
}
if (to_return.valid) {
uint8_t address = (data>>24)&0xff;
uint8_t naddress = (data>>16)&0xff;
uint8_t command = (data>>8)&0xff;
uint8_t ncommand = (data>>0)&0xff;
if (0xff==(address^naddress)) {
to_return.address = address;
} else {
to_return.valid = false;
}
if (0xff==(command^ncommand)) {
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;
}

16
src/ir_nec.h Normal file
View File

@ -0,0 +1,16 @@
/* NEC InfraRed protocol
* more information at http://www.sbprojects.com/knowledge/ir/nec.php
*/
static const uint16_t MARKS[2]={9000,560}; /* mark duration in us [start,bit] */
static const uint16_t SPACES[4]={4500,2250,1680,560}; /* space duration in us [start,repeat,1,0] */
struct nec {
bool valid;
bool repeat;
uint8_t address;
uint8_t command;
};
void time2nec(uint16_t* burst, uint8_t pulses);
struct nec nec2data(uint16_t* burst, uint8_t pulses);

View File

@ -1,6 +1,7 @@
#include <stdint.h> /* Standard Integer Types */
#include <stdio.h> /* Standard IO facilities */
#include <stdlib.h> /* General utilities */
#include <stdbool.h> /* Boolean */
#include <string.h> /* Strings */
#include <avr/io.h> /* AVR device-specific IO definitions */
#include <util/delay.h> /* Convenience functions for busy-wait delay loops */
@ -8,6 +9,7 @@
#include "main.h"
#include "uart.h"
#include "ir_nec.h"
/* global variables */
volatile uint8_t pwr_ok; /* is power ok */
@ -17,9 +19,9 @@ static const uint16_t TIMER2_PRESCALE[8] = {0,1,8,32,64,128,256,1024}; /* timer
volatile uint16_t tachometer = 0; /* the tachometer time (from timer) */
volatile uint8_t ir; /* IR signal state, to measure IR code */
static const uint16_t TIMER1_PRESCALE[8] = {0,1,8,64,256,1024,0,0}; /* timer 1 CS1[2:0] values */
volatile uint8_t pulse = 1; /* pulse index within the burst */
volatile uint8_t pulse = 0; /* pulse index within the burst */
#define PULSE_MAX 128 /* maximum number of pulses to save */
volatile uint16_t burst[PULSE_MAX]; /* pulse times forming a burst (from timer) */
uint16_t burst[PULSE_MAX]; /* pulse times forming a burst (from timer) */
/* power ok interrupt */
@ -67,7 +69,16 @@ ISR(TIMER2_OVF_vect) { /* timer 2 overflow interrupt vector */
/* timer 1 interrupt used to measure IR pulse */
ISR(TIMER1_COMPA_vect) { /* timer 1 OCR1A match interrupt vector */
if (pulse>0) {
pulse2us();
pulse2time(burst,pulse-1);
time2nec(burst,pulse-1);
struct nec ir_data = nec2data(burst,pulse-1);
if (ir_data.valid) {
if (ir_data.repeat) {
printf("IR signal repeated\n");
} else {
printf("IR addr: %u, command: %u\n",ir_data.address,ir_data.command);
}
}
OCR0A = ~OCR0A;
pulse = 0;
}
@ -149,18 +160,19 @@ static void ioinit(void)
}
/* convert burst to micro-seconds */
static void pulse2us(void)
static void pulse2time(uint16_t* burst, uint8_t pulses)
{
uint16_t prescale = TIMER1_PRESCALE[(TCCR1B&((1<<CS12)|(1<<CS11)|(1<<CS10)))>>CS10]; /* timer 1 presacler */
uint16_t tick = F_CPU/(1000*prescale); /* ticks per ms */
//uint16_t time; /* pulse time in us */
if (0==prescale) {
return;
}
for (uint8_t i=0; i<pulse; i++) {
if (0==burst[i]) {
return;
}
burst[i] = (burst[i]*1000UL)/tick;
printf("pulse %u: %uus\n",i,burst[i]);
}
}

View File

@ -17,4 +17,4 @@
#define CH2_5 PD7
static void ioinit(void);
static void pulse2us(void);
static void pulse2time(uint16_t* burst, uint8_t pulses);