Skip to content

Instantly share code, notes, and snippets.

@wararyo
Last active August 29, 2015 13:57
Show Gist options
  • Save wararyo/9913293 to your computer and use it in GitHub Desktop.
Save wararyo/9913293 to your computer and use it in GitHub Desktop.
IR library(Send Only/NEC format)
/*
* IR.h
*
* Created: 2014/03/30 22:35:21
* Author: wararyo
*/
#ifndef IR_H_
#define IR_H_
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#define cbi(addr,bit) addr &= ~(1<<bit)
#define sbi(addr,bit) addr |= (1<<bit)
#define tbi(addr,bit) addr ^= (1<<bit)
#define wait(ms) _delay_ms(ms)
#define TIMER_CONTROL_A TCCR0A
#define TIMER_CONTROL_B TCCR0B
#define TIMER_COMP OCR0A
#define TIMER_INTERRUPT TIMSK0
#define TIMER_INTERRUPT_BIT OCIE0A
#define PWM_CONTROL_A TCCR1A
#define PWM_CONTROL_B TCCR1B
#define PWM_COMP OCR1AL
#define PWM_TOP ICR1
#define CAP_CONTROL_A TCCR1A
#define CAP_CONTROL_B TCCR1B
#define CAP_PERIOD ICR1
#define CAP_DDR DDRB
#define CAP_PIN PB0
#define CAP_EDGESELECT ICES1
#define CAP_INTERRUPT TIMSK1
#define CAP_INTERRUPT_BIT ICIE1
#define CAP_OVF_INTERRUPT_BIT TOIE1
#define IR_LED_DDR DDRB
#define IR_LED_PORT PORTB
#define IR_LED_PIN PB1 //OC1A
#define IR_T 70// 562/8
#define IR_CAREER 26
#define IR_DUTY 9 // 26/3
volatile int IR_count = 0;
volatile char IR_data[96];//16+8+(4*32)+1
volatile int IR_receive_raw[72];
volatile char IR_isSending = 0;
volatile char IR_isReceiving = 0;
ISR ( TIMER0_COMPA_vect ){
if(IR_data[IR_count] & 0b00000001){
sbi(PWM_CONTROL_A,7);
}
else{
cbi(PWM_CONTROL_A,7);
}
TIMER_COMP = IR_T * (IR_data[IR_count] >> 1);
IR_count++;
if(IR_data[IR_count] == 0) {
cbi(PWM_CONTROL_A,7);
cbi(TIMER_INTERRUPT,TIMER_INTERRUPT_BIT);
IR_count = 0;
cbi(IR_LED_PORT,IR_LED_PIN);
IR_isSending = 0;
IR_initialize(0);
IR_onSendFinished();
}
}
ISR ( TIMER1_CAPT_vect ){
static char receive_count = 0;
IR_isReceiving = 1;
tbi(CAP_CONTROL_B,ICES1);
//sbi(PORTD,PD7);
unsigned int span = CAP_PERIOD;
TCNT1 = 0;
IR_receive_raw[receive_count++] = span;
//sendStringLine(itoa(span,&ch,10));
}
//TIMER1のオーバーフローを受信終了とみなす
ISR ( TIMER1_OVF_vect ) {
tbi(PORTD,PD7);
if(!IR_isReceiving) return;
char ch;
for(int i=1;i<72;i++){
sendStringLine(itoa(IR_receive_raw[i] * 8,&ch,10));
}
}
void IR_onSendStart();
void IR_onSendFinished();
void IR_onInitialize();
//mode:0=receive 1=send
void IR_initialize(char mode){
IR_onInitialize();
TIMER_CONTROL_A = 0b00000010;//OC0A切断 CTC
TIMER_CONTROL_B = 0b00000010;//1/8 8us/count
TIMER_COMP = IR_T;
sbi(IR_LED_DDR,IR_LED_PIN);//output
cbi(IR_LED_PORT,IR_LED_PIN);
if(mode) IR_PWM_initialize();
else IR_Capture_initialize();
//sei();
}
void IR_PWM_initialize(){
if(IR_isReceiving) return;
PWM_CONTROL_A = 0b00000010;
PWM_CONTROL_B = 0b00011001;
PWM_TOP = IR_CAREER;
PWM_COMP = IR_DUTY;
}
void IR_Capture_initialize(){
if(IR_isSending) return;
CAP_CONTROL_A = 0b00000000;
CAP_CONTROL_B = 0b10000010;//1/8Clock 8us/count
sbi(CAP_INTERRUPT,CAP_INTERRUPT_BIT);
sbi(CAP_INTERRUPT,CAP_OVF_INTERRUPT_BIT);
IR_StartCapture();
}
//IR_initialize(0)後に呼び出される
void IR_StartCapture(){
cbi(CAP_DDR,CAP_PIN);//input
cbi(CAP_CONTROL_B,ICES1);//立ち下がり割り込み
}
//IR_data一個の構造
//0ビット目でHIGHかLOWか
//残り7ビットでその状態の長さを表す
//ex) 0b00000100 LOWの状態を2カウント続ける 0b00000011 HIGHの状態を1カウント続ける
int add_data_raw(char mvalue,int *count,char length){
char lengthnumber; char rest;//8ビットカウンタ 1MHz 1/8分周より 2048μsまでしか測れない
if(length > 3){ lengthnumber = length / 3; rest = length % 3 ;}
else if(length == 0) return *count;
else {lengthnumber = 0; rest = length;}
mvalue &= 0b00000001;//2以上の場合は1に
for (char i=0;i < lengthnumber;i++){
IR_data[*count] = (3 << 1) | mvalue;
(*count)++;
}
IR_data[(*count)++] = (rest << 1) | mvalue;
return *count;
}
int add_data(char mvalue,int *count){
if(mvalue){
add_data_raw(1,count,1);
add_data_raw(0,count,3);
}
else{
add_data_raw(1,count,1);
add_data_raw(0,count,1);
}
return *count;
}
void IR_send(int customer,char data){
/*int count = 0;
for(char i=0;i < 16;i++){
IR_data[count] = 1;
count++;
}
for(char i=0;i < 8;i++){
IR_data[count] = 0;
count++;
}
for(char i=0;i < 16;i++){
count = add_data(((customer >> (15 - i)) & 0x0001),count);//カスタマーコード 上位ビットからiビット目が1の時
}
for(char i=0;i < 8;i++){
count = add_data(((data >> (7 - i)) & 0x01),count);
/*if((data >> (7 - i)) & 0x01){
IR_data[count] = 1;count++;
IR_data[count] = 0;count++;
}
else{
IR_data[count] = 1;count++;
for(char ii=0;ii < 3;ii++){IR_data[count] = 0;count++;}
}*//*
}
for(char i=0;i < 8;i++){
count = add_data(((~data >> (7 - i)) & 0x01),count);
/*if((~data >> (7 - i)) & 0x01){
IR_data[count] = 1;count++;
IR_data[count] = 0;count++;
}
else{
IR_data[count] = 1;count++;
for(char ii=0;ii < 3;ii++){IR_data[count] = 0;count++;}
}*//*
}
IR_data[count] = 1;
count++;
while(count < 154){
IR_data[count] = 0;
count++;
}*/
int count = 0;
add_data_raw(1,&count,16);
add_data_raw(0,&count,8);
for(char i=0;i < 16;i++){
add_data(((customer >> (15 - i)) & 0x0001),&count);//カスタマーコード 上位ビットからiビット目が1の時
}
for(char i=0;i < 8;i++){
add_data(((data >> (7 - i)) & 0x01),&count);
}
for(char i=0;i < 8;i++){
add_data(((~data >> (7 - i)) & 0x01),&count);
}
add_data_raw(1,&count,1);
add_data_raw(0,&count,1);
while(count < 96){
IR_data[(count)++] = 0;
}
IR_isSending = 1;
IR_initialize(1);
IR_onSendStart();
sbi(TIMER_INTERRUPT,TIMER_INTERRUPT_BIT);
}
#endif /* IR_H_ */
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment