IR NEC protocol decoder added
This commit is contained in:
parent
9883e2d8d6
commit
a3a1aadd02
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
24
src/main.c
24
src/main.c
|
@ -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]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue