#include <avr/io.h> // for GPIO
#include <avr/sleep.h> // for sleep functions
#include <avr/interrupt.h> // for interrupts
#include <util/delay.h> // for delays
#define w digitalWrite
#define IR_PIN 4 // Pin for IR receiver
uint8_t L1 = 0, L2 = 1, L3 = 2, L4 = 3; //pin out 0-4
uint8_t j1 = 0, j2 = 0, j3 = 0, j4 = 0; //flag
// IR code
#define IR_ADDR 0x0 // IR device address
#define i_FAIL 0xFF // IR fail code
#define IR_POWER 0xA2 // IR code for power on/off
#define R1 0x30 //relay1
#define R2 0x18 //relay2
#define R3 0x7A //relay3
#define R4 0x10 //relay4
//on off led
void f1() {
if (j1 == 0){j1 = 1; w(L1, 1); }
else {j1 = 0; w(L1, 0);}}
void f2() {
if (j2 == 0) { j2 = 1; w(L2, 1);}
else {j2 = 0; w(L2, 0);}}
void f3() {
if (j3 == 0) {j3 = 1; w(L3, 1);}
else { j3 = 0; w(L3, 0);}}
void f4() {
if (j4 == 0) {j4 = 1;w(L4, 1);}
else {j4 = 0;w(L4, 0);}}
void of() {
w(L1, 0);
w(L2, 0);
w(L3, 0);
w(L4, 0);
}
// ===================================================================================
// IR Receiver Implementation (NEC Protocol)
// ===================================================================================
// IR receiver definitions and macros
#define IR_init() PORTB |= (1<<IR_PIN) // pullup on IR pin
#define IR_available() (~PINB & (1<<IR_PIN)) // return true if IR line is low
// IR wait for signal change and measure duration
uint8_t IR_waitChange(uint8_t timeout) {
uint8_t pinState = PINB & (1 << IR_PIN); // get current signal state
uint8_t dur = 0; // variable for measuring duration
while ((PINB & (1 << IR_PIN)) == pinState) { // measure length of signal
if (dur++ > timeout) return 0; // exit if timeout
_delay_us(100); // count every 100us
}
return dur; // return time in 100us
}
// IR read data byte
uint8_t IR_readByte(void) {
uint8_t result;
uint8_t dur;
for (uint8_t i = 8; i; i--) { // 8 bits
result >>= 1; // LSB first
if (IR_waitChange(11) < 3) return i_FAIL; // exit if wrong burst length
dur = IR_waitChange(21); // measure length of pause
if (dur < 3) return i_FAIL; // exit if wrong pause length
if (dur > 11) result |= 0x80; // bit "0" or "1" depends on pause duration
}
return result; // return received byte
}
// IR read data according to NEC protocol
uint8_t IR_read(void) {
uint16_t addr; // variable for received address
if (!IR_available()) return i_FAIL; // exit if no signal
if (!IR_waitChange(100)) return i_FAIL; // exit if wrong start burst length
if (IR_waitChange(55) < 35) return i_FAIL; // exit if wrong start pause length
uint8_t addr1 = IR_readByte(); // get first address byte
uint8_t addr2 = IR_readByte(); // get second address byte
uint8_t cmd1 = IR_readByte(); // get first command byte
uint8_t cmd2 = IR_readByte(); // get second command byte
if (IR_waitChange(11) < 3) return i_FAIL; // exit if wrong final burst length
if ((cmd1 + cmd2) < 255) return i_FAIL; // exit if command bytes are not inverse
if ((addr1 + addr2) == 255) addr = addr1; // check if it's extended NEC-protocol ...
else addr = ((uint16_t)addr2 << 8) | addr1; // ... and get the correct address
if (addr != IR_ADDR) return i_FAIL; // wrong address
return cmd1; // return command code
}
// Go to standby mode
void standby(void) {
of(); //off all led
while (1) {
GIFR |= (1 << PCIF); // clear any outstanding interrupts
sei(); // enable interrupts
sleep_mode(); // sleep until IR interrupt
cli(); // disable interrupts
if ( (IR_available()) && (IR_read() == IR_POWER) ) break; // exit on power button
}
}
// Pin change interrupt service routine
EMPTY_INTERRUPT(PCINT0_vect); // just wake up from sleep
int main(void) {
// Disable unused peripherals and prepare sleep mode to save power
ACSR = (1 << ACD); // disable analog comperator
DIDR0 = ~(1 << IR_PIN) & 0x1F; // disable digital intput buffer except IR pin
PRR = (1 << PRADC); // shut down ADC
GIMSK |= (1 << PCIE); // enable pin change interrupts
PCMSK |= (1 << IR_PIN); // enable interrupt on IR pin
set_sleep_mode(SLEEP_MODE_PWR_DOWN); // set sleep mode to power down
// Setup
IR_init(); // init IR receiver
for (int x = 0; x < 3; x++);
// Loop
while (1) {
// Check IR receiver and change parameters; delay 80ms
for (uint8_t i = 80; i; i--) {
if (IR_available()) {
uint8_t command = IR_read();
switch (command) {
case IR_POWER: standby(); break;
case R1 : f1(); break;
case R2 : f2(); break;
case R3 : f3(); break;
case R4 : f4(); break;
default: break;
}
}
_delay_ms(1);
}
}
}