├── Arduino_Ameba_IR_Transmit.png ├── Arduino_UNO_IR_Transmit.png ├── DYIRDaikin.cpp ├── DYIRDaikin.h ├── DYIRDaikinBRC.cpp ├── DYIRDaikinBRC.h ├── DYIRDaikinDef.h ├── DYIRDaikinPWM.h ├── DYIRDaikinRecv.cpp ├── DYIRDaikinRecv.h ├── DYIRDaikinSend.cpp ├── DYIRDaikinSend.h ├── README.md ├── boarddefs.h ├── examples ├── Analytics │ ├── Decode │ │ └── Decode.ino │ ├── RecvPacket │ │ └── RecvPacket.ino │ └── SendMark │ │ └── SendMark.ino ├── BRCPowerOnOff │ └── BRCPowerOnOff.ino ├── Bridge │ └── Bridge.ino ├── LoopTest │ └── LoopTest.ino └── PowerOnOff │ └── PowerOnOff.ino ├── keywords.txt └── library.properties /Arduino_Ameba_IR_Transmit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danny-source/Arduino_DY_IRDaikin/a18c63714b2198db958a65d138c7ce887b9be906/Arduino_Ameba_IR_Transmit.png -------------------------------------------------------------------------------- /Arduino_UNO_IR_Transmit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danny-source/Arduino_DY_IRDaikin/a18c63714b2198db958a65d138c7ce887b9be906/Arduino_UNO_IR_Transmit.png -------------------------------------------------------------------------------- /DYIRDaikin.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | // 5 | void DYIRDaikin::begin() 6 | { 7 | _irsend.begin(); 8 | } 9 | 10 | void DYIRDaikin::begin(int irSendPin, uint8_t irRecvPin) 11 | { 12 | _irsend.begin(irSendPin); 13 | _irrecv.begin(irRecvPin,irReceiveData,25); 14 | } 15 | void DYIRDaikin::begin(int irSendPin) 16 | { 17 | _irsend.begin(irSendPin); 18 | } 19 | 20 | void DYIRDaikin::decodePin(uint8_t irRecvPin) 21 | { 22 | _irrecv.begin(irRecvPin,irReceiveData,25); 23 | } 24 | 25 | 26 | void DYIRDaikin::on() 27 | { 28 | daikin[13] |= 0x01; 29 | checksum(); 30 | } 31 | 32 | void DYIRDaikin::off() 33 | { 34 | daikin[13] &= 0xFE; 35 | checksum(); 36 | } 37 | 38 | void DYIRDaikin::setPower(uint8_t state) 39 | { 40 | if (state == 0) { 41 | off(); 42 | }else { 43 | on(); 44 | } 45 | } 46 | 47 | uint8_t DYIRDaikin::getPower() 48 | { 49 | return (daikin[13] & 0x01); 50 | } 51 | 52 | void DYIRDaikin::setSwing_on() 53 | { 54 | daikin[16] |=0x0f; 55 | checksum(); 56 | } 57 | 58 | void DYIRDaikin::setSwing_off() 59 | { 60 | daikin[16] &=0xf0; 61 | checksum(); 62 | } 63 | 64 | void DYIRDaikin::setSwing(uint8_t state) 65 | { 66 | if (state == 0) { 67 | setSwing_off(); 68 | }else { 69 | setSwing_on(); 70 | } 71 | } 72 | 73 | uint8_t DYIRDaikin::getSwing() 74 | { 75 | uint8_t state = daikin[16] & 0x0f; 76 | if (state == 0x0f) { 77 | return 1; 78 | } 79 | return 0; 80 | } 81 | 82 | void DYIRDaikin::setSwingLR_on() 83 | { 84 | daikin[17] = daikin[17] | 0x0F; 85 | checksum(); 86 | } 87 | 88 | void DYIRDaikin::setSwingLR_off() 89 | { 90 | daikin[17] = daikin[17] & 0xF0; 91 | checksum(); 92 | } 93 | 94 | void DYIRDaikin::setSwingLR(uint8_t state) 95 | { 96 | if (state == 0) { 97 | setSwingLR_off(); 98 | }else { 99 | setSwingLR_on(); 100 | } 101 | } 102 | 103 | uint8_t DYIRDaikin::getSwingLR() 104 | { 105 | return (daikin[17]) & 0x01; 106 | } 107 | 108 | void DYIRDaikin::setMode(uint8_t mode) 109 | { 110 | uint8_t trmode = vModeTable[mode]; 111 | if (mode>=0 && mode <=4) 112 | { 113 | daikin[13] = (trmode << 4) | getPower(); 114 | checksum(); 115 | } 116 | } 117 | 118 | uint8_t DYIRDaikin::getMode() 119 | { 120 | uint8_t mode = (daikin[13] & B01110000) >> 4; 121 | if (mode == 0x6) { 122 | mode = 0; 123 | }else if (mode == 0x3) { 124 | mode = 1; 125 | }else if (mode == 0x2) { 126 | mode = 2; 127 | }else if (mode == 0x4) { 128 | mode = 3; 129 | }else if (mode == 0x0) { 130 | mode = 4; 131 | } 132 | return mode; 133 | } 134 | 135 | // 0~4 speed,5 auto,6 moon 136 | void DYIRDaikin::setFan(uint8_t speed) 137 | { 138 | uint8_t fan = vFanTable[speed]; 139 | if (speed>=0 && speed <=6) 140 | { 141 | daikin[16] &= 0x0f; 142 | daikin[16] |= fan; 143 | checksum(); 144 | } 145 | } 146 | 147 | uint8_t DYIRDaikin::getFan() 148 | { 149 | uint8_t fan = (daikin[16] & 0xf0); 150 | if (fan == 0x30) { 151 | fan = 0; 152 | }else if (fan == 0x40) { 153 | fan = 1; 154 | }else if (fan == 0x50) { 155 | fan = 2; 156 | }else if (fan == 0x60) { 157 | fan = 3; 158 | }else if (fan == 0x70) { 159 | fan = 4; 160 | }else if (fan == 0xa0) { 161 | fan = 5; 162 | }else if (fan == 0xb0) { 163 | fan = 6; 164 | } 165 | return fan; 166 | } 167 | 168 | void DYIRDaikin::setTemp(uint8_t temp) 169 | { 170 | switch (getMode()) { 171 | case 1: // cool 172 | if (temp >= 18 && temp <= 32) { 173 | daikin[14] = temp * 2; 174 | checksum(); 175 | } 176 | break; 177 | case 3: // heat 178 | if (temp >= 10 && temp <= 30) { 179 | daikin[14] = temp * 2; 180 | checksum(); 181 | } 182 | break; 183 | case 4: // auto 184 | if (temp >= 18 && temp <= 30) { 185 | daikin[14] = temp * 2; 186 | checksum(); 187 | } 188 | break; 189 | } 190 | } 191 | 192 | uint8_t DYIRDaikin::getTemp() 193 | { 194 | uint8_t temperature= (daikin[14] & B01111110) >> 1; 195 | return temperature; 196 | } 197 | 198 | void DYIRDaikin::sendCommand() 199 | { 200 | checksum(); 201 | _irsend.sendDaikin(daikin, 8,0); 202 | delay(29); 203 | _irsend.sendDaikin(daikin, 19,8); 204 | } 205 | // 206 | void DYIRDaikin::dump() 207 | { 208 | uint8_t i; 209 | for (i=0; i < DYIRDAIKIN_COMMAND_LENGTH; i++) { 210 | Serial.print(daikin[i],HEX); 211 | Serial.print("-"); 212 | } 213 | } 214 | 215 | void DYIRDaikin::description() 216 | { 217 | //Serial.print(F("\r\n==send buffer==\r\n")); 218 | //Serial.print(F("Power:")); 219 | //Serial.print(getPower(),DEC); 220 | //Serial.println(); 221 | //Serial.print(F("Mode:")); 222 | //Serial.print(getMode(),DEC); 223 | //Serial.println(); 224 | //Serial.print(F("Fan:")); 225 | //Serial.print(getFan(),DEC); 226 | //Serial.println(); 227 | //Serial.print(F("Temperature:")); 228 | //Serial.print(getTemp(),DEC); 229 | //Serial.println(); 230 | //Serial.print(F("Swing:")); 231 | //Serial.print(getSwing(),DEC); 232 | //Serial.println(); 233 | //Serial.print(F("SwingLR:")); 234 | //Serial.print(getSwingLR(),DEC); 235 | //Serial.println(); 236 | _irrecv.descriptionARC(daikin + (sizeof(unsigned char)*8)); 237 | } 238 | 239 | //private function 240 | void DYIRDaikin::checksum() 241 | { 242 | uint8_t sum = 0; 243 | uint8_t i; 244 | 245 | 246 | for(i = 0; i <= 6; i++){ 247 | sum += daikin[i]; 248 | } 249 | 250 | daikin[7] = sum &0xFF; 251 | 252 | sum=0; 253 | for(i = 8; i <= 25; i++){ 254 | sum += daikin[i]; 255 | } 256 | 257 | daikin[26] = sum &0xFF; 258 | 259 | 260 | } 261 | 262 | uint8_t DYIRDaikin::decode() { 263 | if (_irrecv.decode() > 10) { 264 | receivedIRUpdateToSendBuffer(irReceiveData); 265 | return 1; 266 | } 267 | return 0; 268 | } 269 | // 270 | void DYIRDaikin::receivedIRUpdateToSendBuffer(uint8_t *recvData) { 271 | //decode all state 272 | //~ static byte vFanTable[] = { 0x30,0x40,0x50,0x60,0x70,0xa0,0xb0}; 273 | uint8_t temperature= (recvData[6] & B01111110) >> 1; 274 | uint8_t fan = (recvData[8] & 0xf0); 275 | if (fan == 0x30) fan = 0; 276 | if (fan == 0x40) fan = 1; 277 | if (fan == 0x50) fan = 2; 278 | if (fan == 0x60) fan = 3; 279 | if (fan == 0x70) fan = 4; 280 | if (fan == 0xa0) fan = 5; 281 | if (fan == 0xb0) fan = 6; 282 | 283 | uint8_t swing = (recvData[8] & 0x01); 284 | uint8_t swingLR = (recvData[9] & 0x01); 285 | uint8_t powerState = (recvData[5] & 0x01); 286 | uint8_t timerOn = (recvData[5] & 0x02) >> 1; 287 | uint16_t timerOnValue = (uint16_t)recvData[10]|(uint16_t)(recvData[11] & B00000111)<<8; 288 | //~ AAAAAAAA AAAXBBBB BBBBBBBX 289 | uint8_t timerOff = (recvData[5] & 0x04) >> 2; 290 | uint16_t timerOffValue = (uint16_t)((recvData[11] & B11110000) >> 4)|(uint16_t)(recvData[12] & B01111111)<<4; 291 | uint8_t mode = (recvData[5] & B01110000) >> 4; 292 | // 293 | uint16_t timeNow = 0; 294 | 295 | //~ if (packetLength == 3) { 296 | //~ timeNow = (uint16_t)recvData[5]|(uint16_t)(recvData[6] & B00000111)<<8; 297 | //~ } 298 | 299 | //{ 0x6,0x3,0x2,0x4,0x00}; 300 | if (mode == 0x6) { 301 | mode = 0; 302 | }else if (mode == 0x3) { 303 | mode = 1; 304 | }else if (mode == 0x2) { 305 | mode = 2; 306 | }else if (mode == 0x4) { 307 | mode = 3; 308 | }else if (mode == 0x0) { 309 | mode = 4; 310 | } 311 | // 312 | uint8_t econo = (recvData[16] & B00000100) >> 2; 313 | //set all state 314 | setPower(powerState); 315 | setMode(mode); 316 | setFan(fan); 317 | setTemp(temperature); 318 | setSwing(swing); 319 | setSwingLR(swingLR); 320 | 321 | 322 | //~ Serial.print(F("\r\n==receive buffer==\r\n")); 323 | //~ Serial.print(F("Power:")); 324 | //~ Serial.print(powerState,DEC); 325 | //~ Serial.println(); 326 | //~ Serial.print(F("Mode:")); 327 | //~ Serial.print(mode,DEC); 328 | //~ Serial.println(); 329 | //~ Serial.print(F("Fan:")); 330 | //~ Serial.print(fan,DEC); 331 | //~ Serial.println(); 332 | //~ Serial.print(F("Temperature:")); 333 | //~ Serial.print(temperature,DEC); 334 | //~ Serial.println(); 335 | //~ Serial.print(F("Swing:")); 336 | //~ Serial.print(swing,DEC); 337 | //~ Serial.println(); 338 | //~ Serial.print("Econo:"); 339 | //~ Serial.print(econo,DEC); 340 | //~ Serial.println(); 341 | //~ Serial.print("Timer On:"); 342 | //~ Serial.print(timerOn,DEC); 343 | //~ Serial.println(); 344 | //~ Serial.print("Timer On Value:"); 345 | //~ Serial.print((timerOnValue / 60),DEC); 346 | //~ Serial.print(":"); 347 | //~ Serial.print((timerOnValue % 60),DEC); 348 | //~ Serial.println(); 349 | //~ Serial.print("Timer Off:"); 350 | //~ Serial.print(timerOff,DEC); 351 | //~ Serial.println(); 352 | //~ Serial.print("Timer Off Value:"); 353 | //~ Serial.print((timerOffValue / 60),DEC); 354 | //~ Serial.print(":"); 355 | //~ Serial.print((timerOffValue % 60),DEC); 356 | //~ Serial.println(); 357 | //~ Serial.print("Timer Now:"); 358 | //~ Serial.print((timeNow / 60),DEC); 359 | //~ Serial.print(":"); 360 | //~ Serial.print((timeNow % 60),DEC); 361 | //~ Serial.println(); 362 | } 363 | -------------------------------------------------------------------------------- /DYIRDaikin.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef DYIRDaikin_h 3 | #define DYIRDaikin_h 4 | #include 5 | #include 6 | #define DYIRDAIKIN_COMMAND_LENGTH 27 7 | class DYIRDaikin 8 | { 9 | public: 10 | void begin(); 11 | //soft IR 12 | void begin(int irSendPin, uint8_t irRecvPin); 13 | void begin(int irSendPin); 14 | void on(); 15 | void off(); 16 | void setPower(uint8_t state); 17 | void setSwing_on(); 18 | void setSwing_off(); 19 | void setSwing(uint8_t state); 20 | void setSwingLR_on(); 21 | void setSwingLR_off(); 22 | void setSwingLR(uint8_t state); 23 | void setMode(uint8_t mode);//0 FAN, 1 COOL, 2 DRY, 3 HEAT,4 AUTO 24 | void setFan(uint8_t speed);// 0~4 speed,5 auto,6 moon 25 | void setTemp(uint8_t temp);// 18-32 cool, 10-30 heat, 18-30 auto 26 | void sendCommand(); 27 | void dump(); 28 | void description(); 29 | // 30 | uint8_t getPower(); 31 | uint8_t getSwing(); 32 | uint8_t getSwingLR(); 33 | uint8_t getMode(); 34 | uint8_t getFan(); 35 | uint8_t getTemp(); 36 | uint8_t decode(); 37 | void decodePin(uint8_t irRecvPin); 38 | 39 | private: 40 | DYIRDaikinSend _irsend; 41 | DYIRDaikinRecv _irrecv; 42 | unsigned char daikinHeader[8] = { 43 | 0x11,0xDA,0x27,0x00,0xC5,0x00,0x00,0xD7 44 | }; 45 | 46 | unsigned char daikin[DYIRDAIKIN_COMMAND_LENGTH] = { 47 | 0x11,0xDA,0x27,0xF0,0x00,0x00,0x00,0x20, 48 | // 0 1 2 3 4 5 6 7 49 | 0x11,0xDA,0x27,0x00,0x00,0x41,0x1E,0x00, 50 | // 8 9 10 11 12 13 14 15 51 | 0xB0,0x00,0x00,0x00,0x00,0x00,0x00,0xC1,0x80,0x00,0xE3 52 | // 16 17 18 19 20 21 22 23 24 25 26 53 | }; 54 | byte vFanTable[7] = { 0x30,0x40,0x50,0x60,0x70,0xa0,0xb0}; 55 | // 0 FAN 1 COOL 2 DRY 3 HEAT 56 | byte vModeTable[5] = { 0x6,0x3,0x2,0x4,0x00}; 57 | // 58 | uint8_t irReceiveData[25] = {0}; 59 | void checksum(); 60 | // 61 | void receivedIRUpdateToSendBuffer(uint8_t *recvData); 62 | }; 63 | 64 | #endif 65 | -------------------------------------------------------------------------------- /DYIRDaikinBRC.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Arduino IRremote Daikin 2015 3 | * Copyright 2015 danny 4 | * 5 | * 6 | * Arduino PWM declare base on Ken Shirriff's IRremote library. 7 | * http://arcfn.com/2009/08/multi-protocol-infrared-remote-library.html 8 | * 9 | * 10 | */ 11 | 12 | #include 13 | 14 | void DYIRDaikinBRC::begin() 15 | { 16 | _irsend.begin(); 17 | } 18 | void DYIRDaikinBRC::begin(int IRsendPin) 19 | { 20 | _irsend.begin(IRsendPin); 21 | } 22 | 23 | void DYIRDaikinBRC::on() 24 | { 25 | daikinBRC[14] |= 0x01; 26 | checksum(); 27 | } 28 | 29 | void DYIRDaikinBRC::off() 30 | { 31 | daikinBRC[14] &= 0xFE; 32 | checksum(); 33 | } 34 | 35 | void DYIRDaikinBRC::setSwing_on() 36 | { 37 | daikinBRC[18] &=0xfc; 38 | daikinBRC[18] |=0x01; 39 | checksum(); 40 | } 41 | 42 | void DYIRDaikinBRC::setSwing_off() 43 | { 44 | daikinBRC[18] &=0xfc; 45 | daikinBRC[18] |=0x02; 46 | checksum(); 47 | } 48 | 49 | void DYIRDaikinBRC::setMode(int mode) 50 | { 51 | if (mode>=0 && mode <=2) 52 | { 53 | daikinBRC[12] &=0x8f; 54 | daikinBRC[12] |=vModeTableBRC12[mode]; 55 | daikinBRC[14] &=0x8f; 56 | daikinBRC[14] |=vModeTableBRC14[mode]; 57 | checksum(); 58 | } 59 | } 60 | 61 | // 0~4 speed,5 auto,6 moon 62 | void DYIRDaikinBRC::setFan(int speed) 63 | { 64 | uint8_t fan = vFanTableBRC[speed]; 65 | if (speed>=0 && speed <=1) 66 | { 67 | daikinBRC[18] &= 0xdf; 68 | daikinBRC[18] |= fan; 69 | checksum(); 70 | } 71 | } 72 | 73 | void DYIRDaikinBRC::setTemp(uint8_t temp) 74 | { 75 | if (temp >= 18 && temp<=36) 76 | { 77 | temp = temp - 9; 78 | temp = temp << 1; 79 | daikinBRC[17] = temp; 80 | checksum(); 81 | } 82 | } 83 | 84 | void DYIRDaikinBRC::sendCommand() 85 | { 86 | checksum(); 87 | _irsend.sendDaikin(daikinBRC, 7,0); 88 | delay(29); 89 | _irsend.sendDaikin(daikinBRC, 15,7); 90 | } 91 | // 92 | uint8_t DYIRDaikinBRC::checksum() 93 | { 94 | uint8_t sum = 0; 95 | uint8_t i; 96 | 97 | 98 | for (i = 0; i <= 5; i++) { 99 | sum += daikinBRC[i]; 100 | } 101 | 102 | daikinBRC[6] = sum &0xFF; 103 | 104 | sum=0; 105 | for (i = 7; i <= 20; i++) { 106 | sum += daikinBRC[i]; 107 | } 108 | 109 | daikinBRC[21] = sum &0xFF; 110 | return 0; 111 | } 112 | 113 | void DYIRDaikinBRC::dump() 114 | { 115 | uint8_t i; 116 | for (i=0; i < DYIRDAIKINBRC_COMMAND_LENGTH; i++) { 117 | Serial.print(daikinBRC[i],HEX); 118 | Serial.print("-"); 119 | } 120 | } 121 | 122 | uint8_t DYIRDaikinBRC::getPower() 123 | { 124 | return (daikinBRC[14])&0x01; 125 | } 126 | 127 | 128 | -------------------------------------------------------------------------------- /DYIRDaikinBRC.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef DYIRDaikinBRC_h 3 | #define DYIRDaikinBRC_h 4 | #include 5 | #define DYIRDAIKINBRC_COMMAND_LENGTH 22 6 | class DYIRDaikinBRC 7 | { 8 | public: 9 | //void IRdaikin(); 10 | void begin(); 11 | void begin(int IRsendPin); 12 | void on(); 13 | void off(); 14 | void setSwing_on(); 15 | void setSwing_off(); 16 | void setMode(int mode);// 17 | void setFan(int speed);// 0~1 Hi,Low 18 | void setTemp(uint8_t temp);//22 ~ 33 19 | void sendCommand(); 20 | void dump(); 21 | uint8_t getPower(); 22 | private: 23 | 24 | DYIRDaikinSend _irsend; 25 | // # of bytes per command 26 | 27 | unsigned char daikinBRC[DYIRDAIKINBRC_COMMAND_LENGTH] = { 28 | 0x11,0xDA,0x17,0x18,0x04,0x00,0x1E, 29 | //0 1 2 3 4 5 6 30 | 0x11,0xDA,0x17,0x18,0x00,0x73,0x00,0x21,0x00, 31 | //7, 8 9 10 11 12 13 14 15 32 | 0x00,0x20,0x35,0x00,0x20,0x23 }; 33 | //16 17 18 19 20 21 34 | 35 | byte vFanTableBRC[3] = { 0x00,0x20}; 36 | //0 FAN 1 COOL 2 DRY 3 WARM (Xian Li) 37 | byte vModeTableBRC12[4] = { 0x60,0x20,0x70,0x70}; 38 | byte vModeTableBRC14[4] = { 0x00,0x70,0x20,0x10}; 39 | //22,23,24,25,26,27,28,29,30,31,32,33,34,35,36 40 | byte vTempTableBRC[16] = {26,28,30,32,34,36,38,40, 41 | 42,44,46,48,50,52,54 }; 42 | uint8_t checksum(); 43 | ; 44 | }; 45 | 46 | #endif 47 | 48 | -------------------------------------------------------------------------------- /DYIRDaikinDef.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef DYIRDaikinDef_h 3 | #define DYIRDaikinDef_h 4 | 5 | #define DYIRDAIKIN_DEBUG 6 | #define DYIRDAIKIN_DEBUG_SERIAL Serial 7 | 8 | #ifdef DYIRDAIKIN_DEBUG 9 | #define DYIRDAIKIN_DEBUG_PRINT(...) { DYIRDAIKIN_DEBUG_SERIAL.print(__VA_ARGS__); } 10 | #define DYIRDAIKIN_DEBUG_PRINTLN(...) { DYIRDAIKIN_DEBUG_SERIAL.println(__VA_ARGS__); } 11 | #else 12 | #define DYIRDAIKIN_DEBUG_PRINT(...) {} 13 | #define DYIRDAIKIN_DEBUG_PRINTLN(...) {} 14 | #endif 15 | 16 | //#define DY_IRDAIKIN_SOFTIR 17 | 18 | #define AVR_HARDWARE_PWM \ 19 | (defined(__AVR_ATmega1280__) | defined(__AVR_ATmega2560__) | \ 20 | defined(__AVR_AT90USB162__) | defined(__AVR_ATmega32U4__) | \ 21 | defined(__AVR_AT90USB646__) | defined(__AVR_AT90USB1286__) | \ 22 | defined(__AVR_ATmega644P__) | defined(__AVR_ATmega644__) | \ 23 | defined(__AVR_ATmega8P__) | defined(__AVR_ATmega8__) | defined(__AVR_ATmega328P__)) 24 | 25 | #if defined(ARDUINO) && ARDUINO >= 100 26 | #include 27 | #else 28 | #include 29 | #endif 30 | 31 | #if AVR_HARDWARE_PWM 32 | #include 33 | #include 34 | #include 35 | #warning "Use PWM IR to Send!" 36 | #define SOFTIR_PIN 3 37 | #else 38 | #define _delay_us delayMicroseconds 39 | #define TIMER_ENABLE_PWM 40 | #define TIMER_DISABLE_PWM 41 | #define TIMER_CONFIG_KHZ 42 | #define TIMER_PWM_PIN 3 43 | #define SOFTIR_PIN 3 44 | #warning "Use soft IR to Simulate!" 45 | #endif 46 | // 47 | #define DYIRDAIKIN_FREQUENCY 38 48 | 49 | //DAIKIN 50 | #define DYIRDAIKIN_HDR_MARK 3600 //DAIKIN_ZERO_MARK*8 51 | #define DYIRDAIKIN_HDR_SPACE 1600 //DAIKIN_ZERO_MARK*4 52 | #define DYIRDAIKIN_ONE_SPACE 1300 53 | #define DYIRDAIKIN_ONE_MARK 400 54 | #define DYIRDAIKIN_ZERO_MARK 400 55 | #define DYIRDAIKIN_ZERO_SPACE 428 56 | 57 | 58 | // IR detector output is active low 59 | #define MARK 0 60 | #define SPACE 1 61 | 62 | 63 | #endif 64 | -------------------------------------------------------------------------------- /DYIRDaikinPWM.h: -------------------------------------------------------------------------------- 1 | #ifndef DYIRDaikinPWM_h 2 | #define DYIRDaikinPWM_h 3 | 4 | // include Arduino-IRremote PWM declare to keep compatibility 5 | // hardware specification goto https://github.com/z3t0/Arduino-IRremote/blob/master/README.md 6 | // All board specific stuff has been moved to its own file, included here. 7 | #include "boarddefs.h" 8 | // 9 | #endif 10 | 11 | -------------------------------------------------------------------------------- /DYIRDaikinRecv.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | //SAMPLE_DELAY_TIME US 5 | #if (defined(__AVR_ATmega328P__) | defined(__AVR_ATmega8__) | defined(__AVR_ATmega8P__) | defined(__AVR_ATmega32U4__)) 6 | #define SAMPLE_DELAY_TIME (6) 7 | #elif defined(__AVR_ATmega2560__) 8 | #define SAMPLE_DELAY_TIME (2) 9 | #else 10 | #define SAMPLE_DELAY_TIME (10) 11 | #endif 12 | 13 | #define IDLE_TIMER_COUNT ((1000*13)/SAMPLE_DELAY_TIME) 14 | #define BUFFER_SIZE (310) 15 | #define NORMAL_INPUT_STATE (1) 16 | // 17 | #define SIGNAL_TIMEOUT__COUNT (6000/SAMPLE_DELAY_TIME) 18 | #define PACKET_TIMEOUT__COUNT (40000/SAMPLE_DELAY_TIME) 19 | 20 | // 0:none,1:start,2:packet,3:stop,4 packet error,5:wake 21 | #define SIGNAL_PATTERN_START (B00000001) 22 | #define SIGNAL_PATTERN_PACKET (B00000010) 23 | #define SIGNAL_PATTERN_STOP (B00000100) 24 | #define SIGNAL_PATTERN_WAKEUP (B00001000) 25 | #define SIGNAL_PATTERN_PACKET_ERROR (B00010000) 26 | // 27 | #define SIGNAL_PAIRED (2) 28 | 29 | // 30 | #define DYIRDAIKIN_DEBUG_STATE 31 | #define DYIRDAIKIN_DEBUG_PRINT_RAW_BYTES 32 | //FOR MEASURE LOOP TIME 33 | //if define,clock wave output at D3 34 | 35 | //#define DYIRDAIKIN_MEASURE_LOOP_TIME 36 | 37 | #ifdef DYIRDAIKIN_MEASURE_LOOP_TIME 38 | #if (defined(__AVR_ATmega328P__) | defined(__AVR_ATmega8__) | defined(__AVR_ATmega8P__)) 39 | #define DYIRDAIKIN_MEASURE_LOOP_TIME_OUTPUT 40 | #define DYIRDAIKIN_MEASURE_LOOP_TIME_HIGH PORTD = PORTD | B00001000; 41 | #define DYIRDAIKIN_MEASURE_LOOP_TIME_LOW PORTD = PORTD & B11110111; 42 | #elif defined(__AVR_ATmega32U4__) 43 | #warning "__AVR_ATmega32U4__" 44 | #define DYIRDAIKIN_MEASURE_LOOP_TIME_OUTPUT 45 | #define DYIRDAIKIN_MEASURE_LOOP_TIME_HIGH PORTD = PORTD | B00000001; 46 | #define DYIRDAIKIN_MEASURE_LOOP_TIME_LOW PORTD = PORTD & B11111110; 47 | #elif defined(__AVR_ATmega2560__) 48 | #warning "__AVR_ATmega2560__" 49 | #define DYIRDAIKIN_MEASURE_LOOP_TIME_OUTPUT 50 | #define DYIRDAIKIN_MEASURE_LOOP_TIME_HIGH PORTE = PORTE | B00100000; 51 | #define DYIRDAIKIN_MEASURE_LOOP_TIME_LOW PORTE = PORTE & B11011111; 52 | #elif defined(ARDUINO_AMEBA) 53 | #define DYIRDAIKIN_MEASURE_LOOP_TIME_OUTPUT 54 | #define DYIRDAIKIN_MEASURE_LOOP_TIME_HIGH digitalWrite(3,HIGH); 55 | #define DYIRDAIKIN_MEASURE_LOOP_TIME_LOW digitalWrite(3,LOW); 56 | #else 57 | #define DYIRDAIKIN_MEASURE_LOOP_TIME_OUTPUT 58 | #define DYIRDAIKIN_MEASURE_LOOP_TIME_HIGH digitalWrite(3,HIGH); 59 | #define DYIRDAIKIN_MEASURE_LOOP_TIME_LOW digitalWrite(3,LOW); 60 | #endif 61 | #endif 62 | 63 | 64 | uint8_t DYIRDaikinRecv::begin(uint8_t pin,uint8_t *buffer,uint8_t buffer_size) 65 | { 66 | if (buffer_size <24) { 67 | return 0; 68 | } 69 | irPin = pin; 70 | pinMode(irPin,INPUT); 71 | bitMask = B00000001; 72 | bitMask = bitMask << (uint8_t)irPin; 73 | #ifdef DYIRDAIKIN_MEASURE_LOOP_TIME_OUTPUT 74 | pinMode(3,OUTPUT); 75 | #endif 76 | irReceiveDataP0 = buffer; 77 | memset(irReceiveDataP0,0,buffer_size); 78 | hasPacket = 0; 79 | packetCounter = 0; 80 | signalCounter = 0; 81 | bitCounter = 0; 82 | irPatternStateMachine = 0; 83 | wakePatternCounter = 0; 84 | packetLength = 3; 85 | irState = irLastState = digitalRead(irPin); 86 | irReceiveDataLen = 0; 87 | receiveBufferBitPtr = 0; 88 | receiveBufferIndex = 0; 89 | return 1; 90 | } 91 | 92 | 93 | uint8_t DYIRDaikinRecv::decode() { 94 | return dumpPackets(); 95 | } 96 | /* 97 | * 0:none 2:paired 98 | */ 99 | uint8_t DYIRDaikinRecv::isSignalLowHighPaired() 100 | { 101 | irStateBufIdx = irSignalState; 102 | irStateDurationBuf[irStateBufIdx] = irSignalDuation; 103 | #ifdef DYIRDAIKIN_DEBUG_PRINT_SIGNAL_DUATION 104 | if (signalCounter < 310) { 105 | irStateDebugBuf[irStateDebugIdx] = irSignalState; 106 | irStateDurationDebugBuf[irStateDebugIdx] = irSignalDuation; 107 | irStateDebugIdx++; 108 | } 109 | #endif 110 | if (irSignalState == 1) { 111 | return 2; 112 | } 113 | return 0; 114 | } 115 | 116 | // 0:none,1:start,2:packet,3:stop,4 packet error,5:wake 117 | uint8_t DYIRDaikinRecv::decodePerPacket() { 118 | 119 | if (irPatternStateMachine == 0) { 120 | //detect 3 packets pattern that first have 4 zero pattern,it is 3 packets protocol 121 | if (isZeroMatched(irStateDurationBuf[0],irStateDurationBuf[1]) == 1) { 122 | wakePatternCounter++; 123 | if ((wakePatternCounter > 3)) { 124 | if (hasWakupPattern == 0) { 125 | #ifdef DYIRDAIKIN_DEBUG_STATE 126 | DYIRDAIKIN_DEBUG_PRINTLN("wake"); 127 | #endif 128 | hasWakupPattern = 1; 129 | } 130 | return SIGNAL_PATTERN_WAKEUP; 131 | } 132 | } 133 | if (hasWakupPattern == 1) { 134 | if (isStopMatched(irStateDurationBuf[0],irStateDurationBuf[1]) == 1) { 135 | //end of wake pattern 136 | return (SIGNAL_PATTERN_STOP | SIGNAL_PATTERN_WAKEUP); 137 | } 138 | } 139 | //first detect start pattern, it is 2 packets protocol 140 | if (isStartMatched(irStateDurationBuf[0],irStateDurationBuf[1]) == 1) { 141 | wakePatternCounter = 0; 142 | irPatternStateMachine = 1; 143 | packetLength = (hasWakupPattern == 1 ? 3: 2); 144 | receiveBufferBitPtr = 0; 145 | receiveBufferIndex = 0; 146 | memset(receiveBuffer,0,26); 147 | return SIGNAL_PATTERN_START; 148 | } 149 | return 0; 150 | } 151 | 152 | if (irPatternStateMachine == 1) { 153 | if (isStopMatched(irStateDurationBuf[0],irStateDurationBuf[1]) == 1) { 154 | irPatternStateMachine = 0; 155 | wakePatternCounter = 0; 156 | packetCounter++; 157 | endTime = millis(); 158 | startTime = endTime; 159 | return SIGNAL_PATTERN_STOP; 160 | } 161 | if (isZeroMatched(irStateDurationBuf[0],irStateDurationBuf[1]) == 1) { 162 | fillBitToByte(receiveBuffer, 0, &receiveBufferBitPtr, &receiveBufferIndex); 163 | }else { 164 | fillBitToByte(receiveBuffer, 1, &receiveBufferBitPtr, &receiveBufferIndex); 165 | } 166 | return SIGNAL_PATTERN_PACKET; 167 | } 168 | return 0; 169 | } 170 | 171 | uint8_t DYIRDaikinRecv::dumpPackets() { 172 | 173 | for(;;) { 174 | irState = readIR(irPin); 175 | if (irState != irLastState) { 176 | if ((irLastState == 1) && (irState == 0)) { 177 | startTime = millis();//reset big timeout 178 | endTime = startTime; 179 | break; 180 | } 181 | }else { 182 | if (packetCounter > 0) { 183 | endTime = millis(); 184 | if ((endTime - startTime) > 80) { 185 | //big timeout need reset packetCounter, sometimes packet is not completed 186 | hasWakupPattern = 0; 187 | packetCounter = 0; 188 | DYIRDAIKIN_DEBUG_PRINTLN("detect packet is timeout,restart"); 189 | } 190 | } 191 | } 192 | irLastState = irState; 193 | return 0; 194 | } 195 | signalCounter = 0; 196 | bitCounter = 0; 197 | duationCounter = 0; 198 | // 199 | signalTimeoutCounter = 0; 200 | packetTimeoutCounter = 0; 201 | 202 | irLastState = irState = 0; 203 | //parse IR signal 204 | uint8_t result = B00000000; 205 | #ifdef DYIRDAIKIN_DEBUG_PRINT_SIGNAL_DUATION 206 | memset(irStateDebugBuf,0,310); 207 | memset(irStateDurationDebugBuf,0,310); 208 | irStateDebugIdx = 0; 209 | #endif 210 | while (1) { 211 | #ifdef DYIRDAIKIN_MEASURE_LOOP_TIME_OUTPUT 212 | DYIRDAIKIN_MEASURE_LOOP_TIME_LOW 213 | DYIRDAIKIN_MEASURE_LOOP_TIME_HIGH 214 | #endif 215 | irState = readIR(irPin); 216 | if (irState != irLastState) { 217 | irSignalState = irLastState; 218 | irSignalDuation = duationCounter; 219 | signalCounter++; 220 | if (isSignalLowHighPaired() == SIGNAL_PAIRED) { 221 | bitCounter++; 222 | signalTimeoutCounter = 0; 223 | result = decodePerPacket(); 224 | if ((result & SIGNAL_PATTERN_PACKET_ERROR) == SIGNAL_PATTERN_PACKET_ERROR) { 225 | //packet is fail ,restart 226 | irPatternStateMachine = 0; 227 | DYIRDAIKIN_DEBUG_PRINTLN("packet detect is error,restart"); 228 | hasWakupPattern = 0; 229 | packetCounter = 0; 230 | break; 231 | } 232 | if ((result & SIGNAL_PATTERN_WAKEUP) == SIGNAL_PATTERN_WAKEUP) { 233 | duationCounter = 0; 234 | signalCounter = 0; 235 | signalTimeoutCounter = 0; 236 | packetCounter = 0; 237 | break; 238 | } 239 | if ((result & SIGNAL_PATTERN_START) == SIGNAL_PATTERN_START) { 240 | signalCounter = 2; 241 | bitCounter = -1; 242 | } 243 | // 244 | } 245 | //clear counterS 246 | duationCounter = 0; 247 | signalTimeoutCounter = 0; 248 | packetTimeoutCounter= 0; 249 | } 250 | 251 | if (signalTimeoutCounter > SIGNAL_TIMEOUT__COUNT) { 252 | if (irLastState == 1) { 253 | irSignalState = irLastState; 254 | irSignalDuation = duationCounter; 255 | signalCounter++; 256 | if (isSignalLowHighPaired() == SIGNAL_PAIRED) { 257 | bitCounter++; 258 | result = decodePerPacket(); 259 | if (result & SIGNAL_PATTERN_STOP) { 260 | irReceiveDataLen = receiveBufferIndex + 1; 261 | uint8_t offsetIndex = 0; 262 | for (int idx = 0;idx < irReceiveDataLen;idx++) { 263 | irReceiveDataP0[idx] = receiveBuffer[idx]; 264 | } 265 | #ifdef DYIRDAIKIN_DEBUG_PRINT_RAW_BYTES 266 | DYIRDAIKIN_DEBUG_PRINTLN("=Decoded="); 267 | DYIRDAIKIN_DEBUG_PRINT("scount:"); 268 | DYIRDAIKIN_DEBUG_PRINTLN(signalCounter,DEC); 269 | DYIRDAIKIN_DEBUG_PRINT("bytes:"); 270 | DYIRDAIKIN_DEBUG_PRINTLN(irReceiveDataLen,DEC); 271 | DYIRDAIKIN_DEBUG_PRINT("pcount:"); 272 | DYIRDAIKIN_DEBUG_PRINTLN(packetCounter,DEC); 273 | DYIRDAIKIN_DEBUG_PRINT("plength:"); 274 | DYIRDAIKIN_DEBUG_PRINTLN(packetLength,DEC); 275 | DYIRDAIKIN_DEBUG_PRINTLN("--"); 276 | for (int idx = 0;idx < irReceiveDataLen;idx++) { 277 | if (receiveBuffer[idx] < 16) { 278 | DYIRDAIKIN_DEBUG_PRINT("0"); 279 | DYIRDAIKIN_DEBUG_PRINT(receiveBuffer[idx],HEX); 280 | }else{ 281 | DYIRDAIKIN_DEBUG_PRINT(receiveBuffer[idx],HEX); 282 | } 283 | DYIRDAIKIN_DEBUG_PRINT("-"); 284 | } 285 | DYIRDAIKIN_DEBUG_PRINTLN(""); 286 | DYIRDAIKIN_DEBUG_PRINTLN("--"); 287 | #endif 288 | if (checkSum(receiveBuffer,irReceiveDataLen) == 0) { 289 | packetCounter = 0; 290 | DYIRDAIKIN_DEBUG_PRINTLN("-check sum error-restart"); 291 | break; 292 | } 293 | if (packetCounter == packetLength) { 294 | //last packet and data length need than 8 bytes 295 | if (irReceiveDataLen <= 8) { 296 | DYIRDAIKIN_DEBUG_PRINTLN("=data length error="); 297 | hasWakupPattern = 0; 298 | packetCounter = 0; 299 | wakePatternCounter = 0;; 300 | break; 301 | } 302 | DYIRDAIKIN_DEBUG_PRINTLN("=data packet="); 303 | #ifdef DYIRDAIKIN_DEBUG_PRINT_SIGNAL_DUATION 304 | for (int idx = 0;idx < 310;idx++) { 305 | if (irStateDurationDebugBuf[idx] == 0) { 306 | continue; 307 | } 308 | if (irStateDebugBuf[idx] == 0) { 309 | DYIRDAIKIN_DEBUG_PRINT(idx,DEC); 310 | DYIRDAIKIN_DEBUG_PRINT("["); 311 | } 312 | DYIRDAIKIN_DEBUG_PRINT(irStateDebugBuf[idx],DEC); 313 | DYIRDAIKIN_DEBUG_PRINT(","); 314 | DYIRDAIKIN_DEBUG_PRINT(irStateDurationDebugBuf[idx],DEC); 315 | if (irStateDebugBuf[idx] == 0) { 316 | DYIRDAIKIN_DEBUG_PRINT("-"); 317 | } 318 | if (irStateDebugBuf[idx] == 1) { 319 | DYIRDAIKIN_DEBUG_PRINTLN("]"); 320 | } 321 | } 322 | DYIRDAIKIN_DEBUG_PRINT("---"); 323 | #endif 324 | //clear 325 | hasWakupPattern = 0; 326 | packetCounter = 0; 327 | #ifdef DYIRDAIKIN_MEASURE_LOOP_TIME_OUTPUT 328 | DYIRDAIKIN_MEASURE_LOOP_TIME_LOW 329 | #endif 330 | return irReceiveDataLen; 331 | } 332 | DYIRDAIKIN_DEBUG_PRINTLN("=PSP="); 333 | }else if (((result & SIGNAL_PATTERN_STOP)) 334 | && (result & SIGNAL_PATTERN_WAKEUP)) { 335 | DYIRDAIKIN_DEBUG_PRINTLN("=WAKEUP+STOP=1="); 336 | break; 337 | }else { 338 | DYIRDAIKIN_DEBUG_PRINTLN("=Timeout=2=restart"); 339 | hasWakupPattern = 0; 340 | packetCounter = 0; 341 | break; 342 | } 343 | }else if ((result & SIGNAL_PATTERN_WAKEUP)) { 344 | #ifdef DYIRDAIKIN_DEBUG_STATE 345 | DYIRDAIKIN_DEBUG_PRINTLN("=WAKEUP=RET=2="); 346 | #endif 347 | break; 348 | }else { 349 | #ifdef DYIRDAIKIN_DEBUG_STATE 350 | DYIRDAIKIN_DEBUG_PRINTLN("=Timeout=1=restart"); 351 | #endif 352 | hasWakupPattern = 0; 353 | break; 354 | } 355 | duationCounter = 0; 356 | signalCounter = 0; 357 | } 358 | signalTimeoutCounter = 0; 359 | receiveBufferIndex = 0; 360 | break;//###// 361 | }//signal timeout 362 | if (packetTimeoutCounter > PACKET_TIMEOUT__COUNT) { 363 | #ifdef DYIRDAIKIN_DEBUG_STATE 364 | DYIRDAIKIN_DEBUG_PRINTLN("=Detect Packet=Timeout=restart"); 365 | #endif 366 | hasWakupPattern = 0; 367 | packetCounter = 0; 368 | //sometimes overfollow 369 | bitMask = B00000001; 370 | bitMask = bitMask << (uint8_t)irPin; 371 | receiveBufferIndex = 0; 372 | #ifdef DYIRDAIKIN_MEASURE_LOOP_TIME_OUTPUT 373 | DYIRDAIKIN_MEASURE_LOOP_TIME_LOW 374 | #endif 375 | return 0; 376 | } 377 | 378 | irLastState = irState; 379 | _delay_us(SAMPLE_DELAY_TIME); 380 | signalTimeoutCounter++; 381 | packetTimeoutCounter++; 382 | duationCounter++; 383 | //------------------------------------------------------ 384 | #ifdef DYIRDAIKIN_MEASURE_LOOP_TIME_OUTPUT 385 | DYIRDAIKIN_MEASURE_LOOP_TIME_LOW 386 | #endif 387 | }//while 388 | 389 | return 0; 390 | } 391 | 392 | uint8_t DYIRDaikinRecv::checkSum(uint8_t *buffer,uint8_t len) 393 | { 394 | uint8_t sum = 0; 395 | for (uint8_t i =0;i< (len - 1);i++) { 396 | sum = (uint8_t)(sum + buffer[i]); 397 | } 398 | DYIRDAIKIN_DEBUG_PRINTLN(); 399 | if (sum < 16) { 400 | DYIRDAIKIN_DEBUG_PRINT("0"); 401 | DYIRDAIKIN_DEBUG_PRINT(sum,HEX); 402 | }else { 403 | DYIRDAIKIN_DEBUG_PRINT(sum,HEX); 404 | } 405 | DYIRDAIKIN_DEBUG_PRINT("-"); 406 | if (buffer[len - 1] < 16) { 407 | DYIRDAIKIN_DEBUG_PRINT("0"); 408 | DYIRDAIKIN_DEBUG_PRINT(buffer[len - 1],HEX); 409 | }else { 410 | DYIRDAIKIN_DEBUG_PRINT(buffer[len - 1],HEX); 411 | } 412 | if (buffer[len - 1] == sum) { 413 | DYIRDAIKIN_DEBUG_PRINTLN(" CRC OK"); 414 | return 1; 415 | } 416 | DYIRDAIKIN_DEBUG_PRINTLN(" CRC ERR"); 417 | return 0; 418 | } 419 | 420 | void DYIRDaikinRecv::fillBitToByte(uint8_t *buffer, uint8_t value, uint8_t *bitPtr, uint8_t *bufferIndex) { 421 | uint8_t _bitPtr; 422 | uint8_t _bufferIndex; 423 | _bitPtr = *bitPtr; 424 | _bufferIndex = *bufferIndex; 425 | if (_bitPtr > 7) { 426 | _bufferIndex++; 427 | _bitPtr = 0; 428 | }else { 429 | buffer[_bufferIndex] = buffer[_bufferIndex] >> 1; 430 | } 431 | if (value == 1) { 432 | buffer[_bufferIndex] = buffer[_bufferIndex] | B10000000; 433 | } 434 | if (value == 0) { 435 | buffer[_bufferIndex] = buffer[_bufferIndex] & B01111111; 436 | } 437 | _bitPtr++; 438 | *bitPtr = _bitPtr; 439 | *bufferIndex = _bufferIndex; 440 | } 441 | // 442 | void DYIRDaikinRecv::descriptionARC(uint8_t *recvData) { 443 | //~ static byte vFanTable[] = { 0x30,0x40,0x50,0x60,0x70,0xa0,0xb0}; 444 | uint8_t temperature= (recvData[6] & B01111110) >> 1; 445 | uint8_t fan = (recvData[8] & 0xf0); 446 | if (fan == 0x30) fan = 0; 447 | if (fan == 0x40) fan = 1; 448 | if (fan == 0x50) fan = 2; 449 | if (fan == 0x60) fan = 3; 450 | if (fan == 0x70) fan = 4; 451 | if (fan == 0xa0) fan = 5; 452 | if (fan == 0xb0) fan = 6; 453 | 454 | uint8_t swing = (recvData[8] & 0x0f) >> 3; 455 | uint8_t swingLR = (recvData[9] & 0x0f) >> 3; 456 | uint8_t powerState = (recvData[5] & 0x01); 457 | uint8_t timerOn = (recvData[5] & 0x02) >> 1; 458 | uint16_t timerOnValue = (uint16_t)recvData[10]|(uint16_t)(recvData[11] & B00000111)<<8; 459 | //~ AAAAAAAA AAAXBBBB BBBBBBBX 460 | uint8_t timerOff = (recvData[5] & 0x04) >> 2; 461 | uint16_t timerOffValue = (uint16_t)((recvData[11] & B11110000) >> 4)|(uint16_t)(recvData[12] & B01111111)<<4; 462 | uint8_t mode = (recvData[5] & B01110000) >> 4; 463 | // 464 | uint16_t timeNow = 0; 465 | if (packetLength == 3) { 466 | timeNow = (uint16_t)recvData[5]|(uint16_t)(recvData[6] & B00000111)<<8; 467 | } 468 | 469 | //{ 0x6,0x3,0x2,0x4,0x00}; 470 | //0 FAN 1 COOL 2 DRY 3 HEAT 471 | if (mode == 0x6) { 472 | mode = 0; 473 | }else if (mode == 0x3) { 474 | mode = 1; 475 | }else if (mode == 0x2) { 476 | mode = 2; 477 | }else if (mode == 0x4) { 478 | mode = 3; 479 | }else if (mode == 0x0) { 480 | mode = 4; 481 | } 482 | 483 | uint8_t econo = (recvData[16] & B00000100) >> 2; 484 | 485 | DYIRDAIKIN_DEBUG_PRINT(F("\r\n===\r\n")); 486 | DYIRDAIKIN_DEBUG_PRINT(F("Power:")); 487 | DYIRDAIKIN_DEBUG_PRINT(powerState,DEC); 488 | DYIRDAIKIN_DEBUG_PRINTLN(); 489 | DYIRDAIKIN_DEBUG_PRINT(F("Mode:")); 490 | DYIRDAIKIN_DEBUG_PRINT(mode,DEC); 491 | if (mode == 0) { 492 | DYIRDAIKIN_DEBUG_PRINT(F(" (FAN")); 493 | } 494 | if (mode == 1) { 495 | DYIRDAIKIN_DEBUG_PRINT(F(" (COOL")); 496 | } 497 | if (mode == 2) { 498 | DYIRDAIKIN_DEBUG_PRINT(F(" (DRY")); 499 | } 500 | if (mode == 3) { 501 | DYIRDAIKIN_DEBUG_PRINT(F(" (HEAT")); 502 | } 503 | if (mode == 4) { 504 | DYIRDAIKIN_DEBUG_PRINT(F(" (AUTO")); 505 | } 506 | 507 | DYIRDAIKIN_DEBUG_PRINTLN(); 508 | DYIRDAIKIN_DEBUG_PRINT("Fan:"); 509 | DYIRDAIKIN_DEBUG_PRINT(fan,DEC); 510 | DYIRDAIKIN_DEBUG_PRINTLN(); 511 | DYIRDAIKIN_DEBUG_PRINT("Temperature:"); 512 | DYIRDAIKIN_DEBUG_PRINT(temperature,DEC); 513 | DYIRDAIKIN_DEBUG_PRINTLN(); 514 | DYIRDAIKIN_DEBUG_PRINT("Swing:"); 515 | DYIRDAIKIN_DEBUG_PRINT(swing,DEC); 516 | DYIRDAIKIN_DEBUG_PRINTLN(); 517 | DYIRDAIKIN_DEBUG_PRINT("SwingLR:"); 518 | DYIRDAIKIN_DEBUG_PRINT(swingLR,DEC); 519 | DYIRDAIKIN_DEBUG_PRINTLN(); 520 | //~ DYIRDAIKIN_DEBUG_PRINT("Econo:"); 521 | //~ DYIRDAIKIN_DEBUG_PRINT(econo,DEC); 522 | //~ DYIRDAIKIN_DEBUG_PRINTLN(); 523 | //~ DYIRDAIKIN_DEBUG_PRINT("Timer On:"); 524 | //~ DYIRDAIKIN_DEBUG_PRINT(timerOn,DEC); 525 | //~ DYIRDAIKIN_DEBUG_PRINTLN(); 526 | //~ DYIRDAIKIN_DEBUG_PRINT("Timer On Value:"); 527 | //~ DYIRDAIKIN_DEBUG_PRINT((timerOnValue / 60),DEC); 528 | //~ DYIRDAIKIN_DEBUG_PRINT(":"); 529 | //~ DYIRDAIKIN_DEBUG_PRINT((timerOnValue % 60),DEC); 530 | //~ DYIRDAIKIN_DEBUG_PRINTLN(); 531 | //~ DYIRDAIKIN_DEBUG_PRINT("Timer Off:"); 532 | //~ DYIRDAIKIN_DEBUG_PRINT(timerOff,DEC); 533 | //~ DYIRDAIKIN_DEBUG_PRINTLN(); 534 | //~ DYIRDAIKIN_DEBUG_PRINT("Timer Off Value:"); 535 | //~ DYIRDAIKIN_DEBUG_PRINT((timerOffValue / 60),DEC); 536 | //~ DYIRDAIKIN_DEBUG_PRINT(":"); 537 | //~ DYIRDAIKIN_DEBUG_PRINT((timerOffValue % 60),DEC); 538 | //~ DYIRDAIKIN_DEBUG_PRINTLN(); 539 | //~ DYIRDAIKIN_DEBUG_PRINT("Timer Now:"); 540 | //~ DYIRDAIKIN_DEBUG_PRINT((timeNow / 60),DEC); 541 | //~ DYIRDAIKIN_DEBUG_PRINT(":"); 542 | //~ DYIRDAIKIN_DEBUG_PRINT((timeNow % 60),DEC); 543 | //~ DYIRDAIKIN_DEBUG_PRINTLN(); 544 | } 545 | 546 | uint8_t DYIRDaikinRecv::isOneMatched(uint16_t lowTimeCounter,uint16_t highTimecounter) 547 | { 548 | if ((lowTimeCounter > 15 && lowTimeCounter < 60) && ((highTimecounter) >= (lowTimeCounter + lowTimeCounter) && highTimecounter < 150)) { 549 | return 1; 550 | } 551 | return 0; 552 | } 553 | 554 | uint8_t DYIRDaikinRecv::isZeroMatched(uint16_t lowTimeCounter,uint16_t highTimecounter) 555 | { 556 | 557 | if ((lowTimeCounter > 15 && lowTimeCounter < 60) && (highTimecounter >= 10 && highTimecounter < 58)) { 558 | return 1; 559 | } 560 | return 0; 561 | } 562 | 563 | uint8_t DYIRDaikinRecv::isStartMatched(uint16_t lowTimeCounter,uint16_t highTimecounter) 564 | { 565 | if ((lowTimeCounter > 50 && lowTimeCounter < 450) && (highTimecounter > 70 && highTimecounter < 250)) { 566 | return 1; 567 | } 568 | return 0; 569 | } 570 | 571 | uint8_t DYIRDaikinRecv::isStopMatched(uint16_t lowTimeCounter,uint16_t highTimecounter) 572 | { 573 | if ((lowTimeCounter > 20 && lowTimeCounter < 500) && (highTimecounter > 200)) { 574 | return 1; 575 | } 576 | return 0; 577 | } 578 | -------------------------------------------------------------------------------- /DYIRDaikinRecv.h: -------------------------------------------------------------------------------- 1 | #ifndef DYIRDaikinRecv_h 2 | #define DYIRDaikinRecv_h 3 | #include "DYIRDaikinDef.h" 4 | 5 | //#define DYIRDAIKIN_DEBUG_PRINT_SIGNAL_DUATION 6 | 7 | #define readIR(p) digitalRead(p); 8 | 9 | class DYIRDaikinRecv 10 | { 11 | public: 12 | uint8_t begin(uint8_t pin,uint8_t *buffer,uint8_t buffer_size); 13 | uint8_t decode(); 14 | uint8_t dumpPackets(); 15 | void descriptionARC(uint8_t *recvData); 16 | private: 17 | uint8_t irPin = 7; 18 | // 19 | uint8_t irState = 1; 20 | uint8_t irLastState = 1; 21 | uint16_t packetTimeoutCounter = 0; 22 | uint16_t signalTimeoutCounter = 0; //about 120ms 23 | 24 | uint16_t duationCounter =0; 25 | uint16_t bitCounter = 0; 26 | uint16_t signalCounter = 0; 27 | 28 | uint8_t packetCounter =0; 29 | uint8_t packetLength; 30 | uint8_t packetNumber = 0; 31 | 32 | uint8_t hasPacket = 0; 33 | uint8_t hasWakupPattern = 0; 34 | 35 | uint8_t irPatternStateMachine = 0; 36 | 37 | uint8_t wakePatternCounter = 0; 38 | uint8_t *irReceiveDataP0; 39 | uint8_t irReceiveDataLen = 0; 40 | uint8_t irSignalState = 0; 41 | uint16_t irSignalDuation = 0; 42 | uint16_t irStateBufIdx = 0; 43 | uint8_t irStateBuf[2]= {0}; 44 | uint16_t irStateDurationBuf[2] = {0}; 45 | // 46 | uint8_t receiveBuffer[26] = {0}; 47 | uint8_t receiveBufferBitPtr = 0; 48 | uint8_t receiveBufferIndex = 0; 49 | uint8_t bitMask = B00000001; 50 | // 51 | #ifdef DYIRDAIKIN_DEBUG_PRINT_SIGNAL_DUATION 52 | uint8_t irStateDebugBuf[310]= {0}; 53 | uint16_t irStateDurationDebugBuf[310] = {0}; 54 | uint16_t irStateDebugIdx = 0; 55 | #endif 56 | unsigned long startTime; 57 | unsigned long endTime; 58 | 59 | // 60 | uint8_t isSignalLowHighPaired(); 61 | //uint8_t decodePackets(); 62 | uint8_t decodePerPacket(); 63 | uint8_t checkSum(uint8_t *buffer,uint8_t len); 64 | void fillBitToByte(uint8_t *buffer, uint8_t value, uint8_t *bitPtr, uint8_t *bufferIndex); 65 | uint8_t isOneMatched(uint16_t lowTimeCounter,uint16_t highTimecounter); 66 | uint8_t isZeroMatched(uint16_t lowTimeCounter,uint16_t highTimecounter); 67 | uint8_t isStartMatched(uint16_t lowTimeCounter,uint16_t highTimecounter); 68 | uint8_t isStopMatched(uint16_t lowTimeCounter,uint16_t highTimecounter); 69 | }; 70 | #endif 71 | -------------------------------------------------------------------------------- /DYIRDaikinSend.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "DYIRDaikinSend.h" 3 | 4 | void DYIRDaikinSend::begin() 5 | { 6 | IRpin = -1; 7 | enableIROut(DYIRDAIKIN_FREQUENCY); 8 | } 9 | 10 | void DYIRDaikinSend::begin(int IRsendPin) 11 | { 12 | IRpin = IRsendPin; 13 | enableIROut(DYIRDAIKIN_FREQUENCY); 14 | pinMode(IRpin, OUTPUT); 15 | digitalWrite(IRpin, LOW); // When not sending PWM, we want it low 16 | } 17 | 18 | 19 | void DYIRDaikinSend::sendDaikin(unsigned char buf[], int len, int start) { 20 | int data2; 21 | sendIRWarm(); 22 | enableIROut(DYIRDAIKIN_FREQUENCY); 23 | mark(DYIRDAIKIN_HDR_MARK); 24 | space(DYIRDAIKIN_HDR_SPACE); 25 | 26 | for (int i = start; i < start+len; i++) { 27 | data2=buf[i]; 28 | 29 | for (int j = 0; j < 8; j++) { 30 | if ((1 << j & data2)) { 31 | mark(DYIRDAIKIN_ONE_MARK); 32 | space(DYIRDAIKIN_ONE_SPACE); 33 | } 34 | else { 35 | mark(DYIRDAIKIN_ZERO_MARK); 36 | space(DYIRDAIKIN_ZERO_SPACE); 37 | 38 | } 39 | } 40 | 41 | } 42 | mark(DYIRDAIKIN_ONE_MARK); 43 | space(DYIRDAIKIN_ZERO_SPACE); 44 | } 45 | 46 | void DYIRDaikinSend::sendDaikinWake() { 47 | enableIROut(38); 48 | space(DYIRDAIKIN_ZERO_MARK); 49 | // 50 | mark(DYIRDAIKIN_ZERO_MARK); 51 | space(DYIRDAIKIN_ZERO_MARK); 52 | // 53 | mark(DYIRDAIKIN_ZERO_MARK); 54 | space(DYIRDAIKIN_ZERO_MARK); 55 | // 56 | mark(DYIRDAIKIN_ZERO_MARK); 57 | space(DYIRDAIKIN_ZERO_MARK); 58 | // 59 | mark(DYIRDAIKIN_ZERO_MARK); 60 | space(DYIRDAIKIN_ZERO_MARK); 61 | // 62 | mark(DYIRDAIKIN_ZERO_MARK); 63 | space(DYIRDAIKIN_ZERO_MARK); 64 | } 65 | 66 | void DYIRDaikinSend::sendIRWarm() { 67 | digitalWrite(IRpin, HIGH); 68 | delayMicrosecondsEnhance(100); 69 | digitalWrite(IRpin, LOW); 70 | delayMicrosecondsEnhance(5); 71 | } 72 | 73 | void DYIRDaikinSend::sendRaw(unsigned int buf[], int len, int hz) 74 | { 75 | enableIROut(hz); 76 | for (int i = 0; i < len; i++) { 77 | if (i & 1) { 78 | space(buf[i]); 79 | } 80 | else { 81 | mark(buf[i]); 82 | } 83 | } 84 | space(0); // Just to be sure 85 | } 86 | 87 | 88 | void DYIRDaikinSend::mark(int time) { 89 | if (IRpin == -1) { 90 | //Serial.println(); 91 | //Serial.println("PWM"); 92 | TIMER_ENABLE_PWM; // Enable pin 3 PWM output 93 | delayMicrosecondsEnhance(time); 94 | } else { 95 | //Serial.println(); 96 | //Serial.print("SOFT:"); 97 | //Serial.println(halfPeriodicTime); 98 | unsigned long beginTime = micros(); 99 | unsigned long endTime = (unsigned long)time; 100 | unsigned long nowTime = micros(); 101 | while (nowTime - beginTime < endTime) { 102 | digitalWrite(IRpin, HIGH); 103 | //PORTD |= B00000100; 104 | delayMicrosecondsEnhance(halfPeriodicTimeHigh); 105 | digitalWrite(IRpin, LOW); 106 | //PORTD &= B11111011; 107 | delayMicrosecondsEnhance(halfPeriodicTimeLow); 108 | nowTime = micros(); 109 | } 110 | } 111 | } 112 | 113 | /* Leave pin off for time (given in microseconds) */ 114 | void DYIRDaikinSend::space(int time) { 115 | if (IRpin == -1) { 116 | TIMER_DISABLE_PWM; // Disable pin 3 PWM output 117 | delayMicrosecondsEnhance(time); 118 | } else { 119 | digitalWrite(IRpin, LOW); 120 | if (time > 0) { 121 | delayMicrosecondsEnhance(time); 122 | } 123 | } 124 | } 125 | 126 | //~ #endif 127 | 128 | void DYIRDaikinSend::enableIROut(int khz) { 129 | if (IRpin == -1) { 130 | pinMode(TIMER_PWM_PIN, OUTPUT); 131 | TIMER_CONFIG_KHZ(khz); 132 | 133 | } else { 134 | int halfPeriodicTime = (500/khz); // T = 1/f but we need T/2 in microsecond and f is in kHz 135 | int periodicTime = (1000/khz); 136 | #if (AVR_HARDWARE_PWM || defined(DY_IRDAIKIN_SOFTIR)) 137 | #if (defined(__AVR_ATmega2560__)) 138 | halfPeriodicTimeHigh = 4; 139 | #elif (defined(__AVR_ATmega32U4__)) 140 | halfPeriodicTimeHigh = 7; 141 | #else 142 | halfPeriodicTimeHigh = 8; 143 | #endif 144 | #else 145 | halfPeriodicTimeHigh = (periodicTime / 4) * 3; 146 | #endif 147 | digitalWrite(IRpin, LOW); 148 | // 38 kHz -> T = 26.31 microsec (periodic time), half of it is 13 149 | #if (AVR_HARDWARE_PWM || defined(DY_IRDAIKIN_SOFTIR)) 150 | #if (defined(__AVR_ATmega2560__)) 151 | halfPeriodicTimeLow = 0; 152 | #elif (defined(__AVR_ATmega32U4__)) 153 | halfPeriodicTimeLow = 0; 154 | #else 155 | halfPeriodicTimeLow = 0; 156 | #endif 157 | #else 158 | halfPeriodicTimeLow = (periodicTime / 4) + (periodicTime % 4); 159 | #endif 160 | } 161 | } 162 | 163 | void DYIRDaikinSend::delayMicrosecondsEnhance(uint32_t usec) 164 | { 165 | #if AVR_HARDWARE_PWM 166 | if (usec > 4) { 167 | unsigned long tStart = micros(); 168 | unsigned long tEnd = tStart + usec - 4; 169 | #else 170 | if (usec > 2) { 171 | unsigned long tStart = micros(); 172 | unsigned long tEnd = tStart + usec - 2; 173 | #endif 174 | if (tEnd < tStart) { // Check if overflow 175 | while ( micros() > tStart ) {} // wait until overflow 176 | } 177 | while ( micros() < tEnd ) {} // normal wait 178 | } 179 | } 180 | 181 | -------------------------------------------------------------------------------- /DYIRDaikinSend.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef DYIRDaikinSend_h 3 | #define DYIRDaikinSend_h 4 | #include "DYIRDaikinDef.h" 5 | 6 | 7 | class DYIRDaikinSend 8 | { 9 | public: 10 | DYIRDaikinSend() {} 11 | void begin(); 12 | void begin(int IRsendPin); 13 | void sendRaw(unsigned int buf[], int len, int hz); 14 | void sendDaikin(unsigned char buf[], int len,int start); 15 | void sendDaikinWake(); 16 | // private: 17 | void enableIROut(int khz); 18 | void mark(int usec); 19 | void space(int usec); 20 | void delayMicrosecondsEnhance(uint32_t usec); 21 | private: 22 | void sendIRWarm(); 23 | int halfPeriodicTimeHigh; 24 | int halfPeriodicTimeLow; 25 | int IRpin; 26 | }; 27 | 28 | #endif 29 | 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | ## Arduino_DY_IRDaikin ARC/BRC 3 | 4 | Arduino_DY_IRDaikin ARC/BRC 5 | 6 | 7 | Start:Sep, 2014 8 | 9 | Copyright 2017 danny 10 | 11 | Orignal name is Arduino_IRremote_Daikin, change to this name now. 12 | 13 | Arduino_DY_IRDaikin ARC/BRC library base from Ken Shirriff's IRremote library. 14 | 15 | Arduino_DY_IRDaikin ARC/BRC is simply to send ir command to control daikin air conditioning ARC/BRC. 16 | 17 | ### Arduino UNO 18 | ![](https://raw.githubusercontent.com/danny-source/Arduino_IRremote_Daikin/master/Arduino_UNO_IR_Transmit.png) 19 | 20 | ### Ameba Arduino 21 | 22 | ![](https://raw.githubusercontent.com/danny-source/Arduino_IRremote_Daikin/master/Arduino_Ameba_IR_Transmit.png) 23 | 24 | ## Changelog: 25 | 26 | 1.1.2 fix PWM frequency and refactory DYIRDaikinRecv class 27 | 28 | 1.1.1 fix soft ir frequency and wave width problem 29 | 30 | 1.1.0 change class and function name,support STM32Duino/Arduino ESP8266/Ameba and Arduino PWM IR Signal,Arduino UNO/Nano/mega 2560 support SOFT IR 31 | 32 | 1.0.2 Support ESP8266/Ameba Soft and Arduino PWM IR Signal 33 | 34 | 1.0.1 Support ESP8266 Soft and Arduino PWM IR Signal 35 | 36 | 1.0.0 Refactory code and ARC support decode ir. 37 | 38 | 0.0.5 In order to isolate,IRremote renamed IRremoteDaikin and refactory,: 39 | 40 | ## PWM Pinout 41 | 42 | ### UNO 43 | 44 | - pin 3:D3 45 | 46 | ### Leonardo 47 | 48 | - pin 2:D2 49 | 50 | ### Mega 51 | 52 | - pin 9:D9 53 | 54 | ## SOFT Pinout 55 | 56 | Default is pin 3 when you use `begin()`.Remeber! SOFT IR must assign pin by `begin(int irSendPin)` 57 | 58 | ### ESP8266 59 | 60 | - pin 4:GPIO4 61 | - pin 5:GPIO5 62 | 63 | ### Ameba RTL8195 64 | 65 | - pin 2:D2 66 | - pin 3:D3 67 | - pin 4:D4 68 | - pin 5:D5 69 | - pin 6:D6 70 | - pin 7:D7 71 | 72 | ### Ameba RTL8710 73 | 74 | - pin 2:D2 75 | - pin 5:D5 76 | 77 | ### STM32F1 78 | 79 | - pin 2:PA2 80 | - pin 3:PA3 81 | 82 | ## Setting function Daikin ARC: 83 | 84 | - on();//turn on AC 85 | - off();//turn off AC 86 | - setSwing_on();//turn on swing 87 | - setSwing_off();//turn off swing 88 | - setMode(int mode);//0=FAN, 1=COOL, 2=DRY, 3=HEAT(if you have one) 89 | - setFan(int speed);// 0~4=speed(1,2,3,4,5),5=auto,6=moon 90 | - setTemp(int temp);// 18-32 cool, 10-30 heat, 18-30 auto 91 | - sendCommand(); 92 | - decode();//decode ir 93 | - description();//print switch state 94 | 95 | ## Setting function Daikin BRC: 96 | 97 | - on();//turn on AC 98 | - off();//turn off AC 99 | - setSwing_on();//turn on swing 100 | - setSwing_off();//turn off swing 101 | - setFan(int speed);// 0.Low 1.High 102 | - setTemp(int temp);//18 ~ 36 Celsius 103 | - sendCommand(); 104 | 105 | ## Execute function: 106 | 107 | - sendCommand(); 108 | 109 | You must initial setting by your programming and, 110 | After Setting execute sendCommand() 111 | 112 | ## Example Daikin ARC: 113 | 114 | ``` 115 | begin(); 116 | on(); 117 | setSwing_off(); 118 | setMode(1) 119 | setFan(4);//FAN speed to MAX 120 | setTemp(25); 121 | //----everything is ok and to execute send command----- 122 | description(); 123 | sendCommand(); 124 | ``` 125 | 126 | ## Thanks 127 | 128 | `Kwok Fai Fong` help me build Daikin BRC remote control support. 129 | 130 | ## Donate 131 | 132 | [![Donate with PayPal](https://raw.githubusercontent.com/stefan-niedermann/paypal-donate-button/master/paypal-donate-button.png)](https://www.paypal.me/dannytwdanny) 133 | -------------------------------------------------------------------------------- /boarddefs.h: -------------------------------------------------------------------------------- 1 | //****************************************************************************** 2 | // IRremote 3 | // Version 2.0.1 June, 2015 4 | // Copyright 2009 Ken Shirriff 5 | // For details, see http://arcfn.com/2009/08/multi-protocol-infrared-remote-library.html 6 | 7 | // This file contains all board specific information. It was previously contained within 8 | // IRremoteInt.h 9 | 10 | // Modified by Paul Stoffregen to support other boards and timers 11 | // 12 | // Interrupt code based on NECIRrcv by Joe Knapp 13 | // http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1210243556 14 | // Also influenced by http://zovirl.com/2008/11/12/building-a-universal-remote-with-an-arduino/ 15 | // 16 | // JVC and Panasonic protocol added by Kristian Lauszus (Thanks to zenwheel and other people at the original blog post) 17 | // Whynter A/C ARC-110WD added by Francesco Meschia 18 | //****************************************************************************** 19 | 20 | #ifndef boarddefs_h 21 | #define boarddefs_h 22 | 23 | //------------------------------------------------------------------------------ 24 | // Defines for blinking the LED 25 | // 26 | 27 | #if defined(CORE_LED0_PIN) 28 | # define BLINKLED CORE_LED0_PIN 29 | # define BLINKLED_ON() (digitalWrite(CORE_LED0_PIN, HIGH)) 30 | # define BLINKLED_OFF() (digitalWrite(CORE_LED0_PIN, LOW)) 31 | 32 | #elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) 33 | # define BLINKLED 13 34 | # define BLINKLED_ON() (PORTB |= B10000000) 35 | # define BLINKLED_OFF() (PORTB &= B01111111) 36 | 37 | #elif defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644__) 38 | # define BLINKLED 0 39 | # define BLINKLED_ON() (PORTD |= B00000001) 40 | # define BLINKLED_OFF() (PORTD &= B11111110) 41 | 42 | // No system LED on ESP32, disable blinking 43 | #elif defined(ESP32) 44 | # define BLINKLED 255 45 | # define BLINKLED_ON() 1 46 | # define BLINKLED_OFF() 1 47 | #else 48 | # define BLINKLED 13 49 | # define BLINKLED_ON() (PORTB |= B00100000) 50 | # define BLINKLED_OFF() (PORTB &= B11011111) 51 | #endif 52 | 53 | //------------------------------------------------------------------------------ 54 | // CPU Frequency 55 | // 56 | #ifdef F_CPU 57 | # define SYSCLOCK F_CPU // main Arduino clock 58 | #else 59 | # define SYSCLOCK 16000000 // main Arduino clock 60 | #endif 61 | 62 | // microseconds per clock interrupt tick 63 | #define USECPERTICK 50 64 | 65 | //------------------------------------------------------------------------------ 66 | // Define which timer to use 67 | // 68 | // Uncomment the timer you wish to use on your board. 69 | // If you are using another library which uses timer2, you have options to 70 | // switch IRremote to use a different timer. 71 | // 72 | 73 | // Arduino Mega 74 | #if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) 75 | //#define IR_USE_TIMER1 // tx = pin 11 76 | #define IR_USE_TIMER2 // tx = pin 9 77 | //#define IR_USE_TIMER3 // tx = pin 5 78 | //#define IR_USE_TIMER4 // tx = pin 6 79 | //#define IR_USE_TIMER5 // tx = pin 46 80 | 81 | // Teensy 1.0 82 | #elif defined(__AVR_AT90USB162__) 83 | #define IR_USE_TIMER1 // tx = pin 17 84 | 85 | // Teensy 2.0 86 | #elif defined(__AVR_ATmega32U4__) 87 | //#define IR_USE_TIMER1 // tx = pin 14 88 | //#define IR_USE_TIMER3 // tx = pin 9 89 | #define IR_USE_TIMER4_HS // tx = pin 10 90 | 91 | // Teensy 3.0 / Teensy 3.1 92 | #elif defined(__MK20DX128__) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__) 93 | #define IR_USE_TIMER_CMT // tx = pin 5 94 | 95 | // Teensy-LC 96 | #elif defined(__MKL26Z64__) 97 | #define IR_USE_TIMER_TPM1 // tx = pin 16 98 | 99 | // Teensy++ 1.0 & 2.0 100 | #elif defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__) 101 | //#define IR_USE_TIMER1 // tx = pin 25 102 | #define IR_USE_TIMER2 // tx = pin 1 103 | //#define IR_USE_TIMER3 // tx = pin 16 104 | 105 | // MightyCore - ATmega1284 106 | #elif defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) 107 | //#define IR_USE_TIMER1 // tx = pin 13 108 | #define IR_USE_TIMER2 // tx = pin 14 109 | //#define IR_USE_TIMER3 // tx = pin 6 110 | 111 | // MightyCore - ATmega164, ATmega324, ATmega644 112 | #elif defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) \ 113 | || defined(__AVR_ATmega324P__) || defined(__AVR_ATmega324A__) \ 114 | || defined(__AVR_ATmega324PA__) || defined(__AVR_ATmega164A__) \ 115 | || defined(__AVR_ATmega164P__) 116 | //#define IR_USE_TIMER1 // tx = pin 13 117 | #define IR_USE_TIMER2 // tx = pin 14 118 | 119 | //MegaCore - ATmega64, ATmega128 120 | #elif defined(__AVR_ATmega64__) || defined(__AVR_ATmega128__) 121 | #define IR_USE_TIMER1 // tx = pin 13 122 | 123 | // MightyCore - ATmega8535, ATmega16, ATmega32 124 | #elif defined(__AVR_ATmega8535__) || defined(__AVR_ATmega16__) || defined(__AVR_ATmega32__) 125 | #define IR_USE_TIMER1 // tx = pin 13 126 | 127 | // Atmega8 128 | #elif defined(__AVR_ATmega8__) 129 | #define IR_USE_TIMER1 // tx = pin 9 130 | 131 | // ATtiny84 132 | #elif defined(__AVR_ATtiny84__) 133 | #define IR_USE_TIMER1 // tx = pin 6 134 | 135 | //ATtiny85 136 | #elif defined(__AVR_ATtiny85__) 137 | #define IR_USE_TIMER_TINY0 // tx = pin 1 138 | 139 | #elif defined(ESP32) 140 | #define IR_TIMER_USE_ESP32 141 | #else 142 | // Arduino Duemilanove, Diecimila, LilyPad, Mini, Fio, Nano, etc 143 | // ATmega48, ATmega88, ATmega168, ATmega328 144 | //#define IR_USE_TIMER1 // tx = pin 9 145 | #define IR_USE_TIMER2 // tx = pin 3 146 | 147 | #endif 148 | 149 | //------------------------------------------------------------------------------ 150 | // Defines for Timer 151 | 152 | //--------------------------------------------------------- 153 | // Timer2 (8 bits) 154 | // 155 | #if defined(IR_USE_TIMER2) 156 | 157 | #define TIMER_RESET 158 | #define TIMER_ENABLE_PWM (TCCR2A |= _BV(COM2B1)) 159 | #define TIMER_DISABLE_PWM (TCCR2A &= ~(_BV(COM2B1))) 160 | #define TIMER_ENABLE_INTR (TIMSK2 = _BV(OCIE2A)) 161 | #define TIMER_DISABLE_INTR (TIMSK2 = 0) 162 | #define TIMER_INTR_NAME TIMER2_COMPA_vect 163 | 164 | #define TIMER_CONFIG_KHZ(val) ({ \ 165 | const uint8_t pwmval = SYSCLOCK / 2000 / (val); \ 166 | TCCR2A = _BV(WGM20); \ 167 | TCCR2B = _BV(WGM22) | _BV(CS20); \ 168 | OCR2A = pwmval; \ 169 | OCR2B = pwmval / 3; \ 170 | }) 171 | 172 | #define TIMER_COUNT_TOP (SYSCLOCK * USECPERTICK / 1000000) 173 | 174 | //----------------- 175 | #if (TIMER_COUNT_TOP < 256) 176 | # define TIMER_CONFIG_NORMAL() ({ \ 177 | TCCR2A = _BV(WGM21); \ 178 | TCCR2B = _BV(CS20); \ 179 | OCR2A = TIMER_COUNT_TOP; \ 180 | TCNT2 = 0; \ 181 | }) 182 | #else 183 | # define TIMER_CONFIG_NORMAL() ({ \ 184 | TCCR2A = _BV(WGM21); \ 185 | TCCR2B = _BV(CS21); \ 186 | OCR2A = TIMER_COUNT_TOP / 8; \ 187 | TCNT2 = 0; \ 188 | }) 189 | #endif 190 | 191 | //----------------- 192 | #if defined(CORE_OC2B_PIN) 193 | # define TIMER_PWM_PIN CORE_OC2B_PIN // Teensy 194 | #elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) 195 | # define TIMER_PWM_PIN 9 // Arduino Mega 196 | #elif defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) \ 197 | || defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) \ 198 | || defined(__AVR_ATmega324P__) || defined(__AVR_ATmega324A__) \ 199 | || defined(__AVR_ATmega324PA__) || defined(__AVR_ATmega164A__) \ 200 | || defined(__AVR_ATmega164P__) 201 | # define TIMER_PWM_PIN 14 // MightyCore 202 | #else 203 | # define TIMER_PWM_PIN 3 // Arduino Duemilanove, Diecimila, LilyPad, etc 204 | #endif // ATmega48, ATmega88, ATmega168, ATmega328 205 | 206 | //--------------------------------------------------------- 207 | // Timer1 (16 bits) 208 | // 209 | #elif defined(IR_USE_TIMER1) 210 | 211 | #define TIMER_RESET 212 | #define TIMER_ENABLE_PWM (TCCR1A |= _BV(COM1A1)) 213 | #define TIMER_DISABLE_PWM (TCCR1A &= ~(_BV(COM1A1))) 214 | 215 | //----------------- 216 | #if defined(__AVR_ATmega8__) || defined(__AVR_ATmega8535__) \ 217 | || defined(__AVR_ATmega16__) || defined(__AVR_ATmega32__) \ 218 | || defined(__AVR_ATmega64__) || defined(__AVR_ATmega128__) 219 | # define TIMER_ENABLE_INTR (TIMSK |= _BV(OCIE1A)) 220 | # define TIMER_DISABLE_INTR (TIMSK &= ~_BV(OCIE1A)) 221 | #else 222 | # define TIMER_ENABLE_INTR (TIMSK1 = _BV(OCIE1A)) 223 | # define TIMER_DISABLE_INTR (TIMSK1 = 0) 224 | #endif 225 | 226 | //----------------- 227 | #define TIMER_INTR_NAME TIMER1_COMPA_vect 228 | 229 | #define TIMER_CONFIG_KHZ(val) ({ \ 230 | const uint16_t pwmval = SYSCLOCK / 2000 / (val); \ 231 | TCCR1A = _BV(WGM11); \ 232 | TCCR1B = _BV(WGM13) | _BV(CS10); \ 233 | ICR1 = pwmval; \ 234 | OCR1A = pwmval / 3; \ 235 | }) 236 | 237 | #define TIMER_CONFIG_NORMAL() ({ \ 238 | TCCR1A = 0; \ 239 | TCCR1B = _BV(WGM12) | _BV(CS10); \ 240 | OCR1A = SYSCLOCK * USECPERTICK / 1000000; \ 241 | TCNT1 = 0; \ 242 | }) 243 | 244 | //----------------- 245 | #if defined(CORE_OC1A_PIN) 246 | # define TIMER_PWM_PIN CORE_OC1A_PIN // Teensy 247 | #elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) 248 | # define TIMER_PWM_PIN 11 // Arduino Mega 249 | #elif defined(__AVR_ATmega64__) || defined(__AVR_ATmega128__) 250 | # define TIMER_PWM_PIN 13 // MegaCore 251 | #elif defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) \ 252 | || defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) \ 253 | || defined(__AVR_ATmega324P__) || defined(__AVR_ATmega324A__) \ 254 | || defined(__AVR_ATmega324PA__) || defined(__AVR_ATmega164A__) \ 255 | || defined(__AVR_ATmega164P__) || defined(__AVR_ATmega32__) \ 256 | || defined(__AVR_ATmega16__) || defined(__AVR_ATmega8535__) 257 | # define TIMER_PWM_PIN 13 // MightyCore 258 | #elif defined(__AVR_ATtiny84__) 259 | # define TIMER_PWM_PIN 6 260 | #else 261 | # define TIMER_PWM_PIN 9 // Arduino Duemilanove, Diecimila, LilyPad, etc 262 | #endif // ATmega48, ATmega88, ATmega168, ATmega328 263 | 264 | //--------------------------------------------------------- 265 | // Timer3 (16 bits) 266 | // 267 | #elif defined(IR_USE_TIMER3) 268 | 269 | #define TIMER_RESET 270 | #define TIMER_ENABLE_PWM (TCCR3A |= _BV(COM3A1)) 271 | #define TIMER_DISABLE_PWM (TCCR3A &= ~(_BV(COM3A1))) 272 | #define TIMER_ENABLE_INTR (TIMSK3 = _BV(OCIE3A)) 273 | #define TIMER_DISABLE_INTR (TIMSK3 = 0) 274 | #define TIMER_INTR_NAME TIMER3_COMPA_vect 275 | 276 | #define TIMER_CONFIG_KHZ(val) ({ \ 277 | const uint16_t pwmval = SYSCLOCK / 2000 / (val); \ 278 | TCCR3A = _BV(WGM31); \ 279 | TCCR3B = _BV(WGM33) | _BV(CS30); \ 280 | ICR3 = pwmval; \ 281 | OCR3A = pwmval / 3; \ 282 | }) 283 | 284 | #define TIMER_CONFIG_NORMAL() ({ \ 285 | TCCR3A = 0; \ 286 | TCCR3B = _BV(WGM32) | _BV(CS30); \ 287 | OCR3A = SYSCLOCK * USECPERTICK / 1000000; \ 288 | TCNT3 = 0; \ 289 | }) 290 | 291 | //----------------- 292 | #if defined(CORE_OC3A_PIN) 293 | # define TIMER_PWM_PIN CORE_OC3A_PIN // Teensy 294 | #elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) 295 | # define TIMER_PWM_PIN 5 // Arduino Mega 296 | #elif defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) 297 | # define TIMER_PWM_PIN 6 // MightyCore 298 | #else 299 | # error "Please add OC3A pin number here\n" 300 | #endif 301 | 302 | //--------------------------------------------------------- 303 | // Timer4 (10 bits, high speed option) 304 | // 305 | #elif defined(IR_USE_TIMER4_HS) 306 | 307 | #define TIMER_RESET 308 | #define TIMER_ENABLE_PWM (TCCR4A |= _BV(COM4A1)) 309 | #define TIMER_DISABLE_PWM (TCCR4A &= ~(_BV(COM4A1))) 310 | #define TIMER_ENABLE_INTR (TIMSK4 = _BV(TOIE4)) 311 | #define TIMER_DISABLE_INTR (TIMSK4 = 0) 312 | #define TIMER_INTR_NAME TIMER4_OVF_vect 313 | 314 | #define TIMER_CONFIG_KHZ(val) ({ \ 315 | const uint16_t pwmval = SYSCLOCK / 2000 / (val); \ 316 | TCCR4A = (1<> 8; \ 322 | OCR4C = pwmval; \ 323 | TC4H = (pwmval / 3) >> 8; \ 324 | OCR4A = (pwmval / 3) & 255; \ 325 | }) 326 | 327 | #define TIMER_CONFIG_NORMAL() ({ \ 328 | TCCR4A = 0; \ 329 | TCCR4B = _BV(CS40); \ 330 | TCCR4C = 0; \ 331 | TCCR4D = 0; \ 332 | TCCR4E = 0; \ 333 | TC4H = (SYSCLOCK * USECPERTICK / 1000000) >> 8; \ 334 | OCR4C = (SYSCLOCK * USECPERTICK / 1000000) & 255; \ 335 | TC4H = 0; \ 336 | TCNT4 = 0; \ 337 | }) 338 | 339 | //----------------- 340 | #if defined(CORE_OC4A_PIN) 341 | # define TIMER_PWM_PIN CORE_OC4A_PIN // Teensy 342 | #elif defined(__AVR_ATmega32U4__) 343 | # define TIMER_PWM_PIN 13 // Leonardo 344 | #else 345 | # error "Please add OC4A pin number here\n" 346 | #endif 347 | 348 | //--------------------------------------------------------- 349 | // Timer4 (16 bits) 350 | // 351 | #elif defined(IR_USE_TIMER4) 352 | 353 | #define TIMER_RESET 354 | #define TIMER_ENABLE_PWM (TCCR4A |= _BV(COM4A1)) 355 | #define TIMER_DISABLE_PWM (TCCR4A &= ~(_BV(COM4A1))) 356 | #define TIMER_ENABLE_INTR (TIMSK4 = _BV(OCIE4A)) 357 | #define TIMER_DISABLE_INTR (TIMSK4 = 0) 358 | #define TIMER_INTR_NAME TIMER4_COMPA_vect 359 | 360 | #define TIMER_CONFIG_KHZ(val) ({ \ 361 | const uint16_t pwmval = SYSCLOCK / 2000 / (val); \ 362 | TCCR4A = _BV(WGM41); \ 363 | TCCR4B = _BV(WGM43) | _BV(CS40); \ 364 | ICR4 = pwmval; \ 365 | OCR4A = pwmval / 3; \ 366 | }) 367 | 368 | #define TIMER_CONFIG_NORMAL() ({ \ 369 | TCCR4A = 0; \ 370 | TCCR4B = _BV(WGM42) | _BV(CS40); \ 371 | OCR4A = SYSCLOCK * USECPERTICK / 1000000; \ 372 | TCNT4 = 0; \ 373 | }) 374 | 375 | //----------------- 376 | #if defined(CORE_OC4A_PIN) 377 | # define TIMER_PWM_PIN CORE_OC4A_PIN 378 | #elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) 379 | # define TIMER_PWM_PIN 6 // Arduino Mega 380 | #else 381 | # error "Please add OC4A pin number here\n" 382 | #endif 383 | 384 | //--------------------------------------------------------- 385 | // Timer5 (16 bits) 386 | // 387 | #elif defined(IR_USE_TIMER5) 388 | 389 | #define TIMER_RESET 390 | #define TIMER_ENABLE_PWM (TCCR5A |= _BV(COM5A1)) 391 | #define TIMER_DISABLE_PWM (TCCR5A &= ~(_BV(COM5A1))) 392 | #define TIMER_ENABLE_INTR (TIMSK5 = _BV(OCIE5A)) 393 | #define TIMER_DISABLE_INTR (TIMSK5 = 0) 394 | #define TIMER_INTR_NAME TIMER5_COMPA_vect 395 | 396 | #define TIMER_CONFIG_KHZ(val) ({ \ 397 | const uint16_t pwmval = SYSCLOCK / 2000 / (val); \ 398 | TCCR5A = _BV(WGM51); \ 399 | TCCR5B = _BV(WGM53) | _BV(CS50); \ 400 | ICR5 = pwmval; \ 401 | OCR5A = pwmval / 3; \ 402 | }) 403 | 404 | #define TIMER_CONFIG_NORMAL() ({ \ 405 | TCCR5A = 0; \ 406 | TCCR5B = _BV(WGM52) | _BV(CS50); \ 407 | OCR5A = SYSCLOCK * USECPERTICK / 1000000; \ 408 | TCNT5 = 0; \ 409 | }) 410 | 411 | //----------------- 412 | #if defined(CORE_OC5A_PIN) 413 | # define TIMER_PWM_PIN CORE_OC5A_PIN 414 | #elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) 415 | # define TIMER_PWM_PIN 46 // Arduino Mega 416 | #else 417 | # error "Please add OC5A pin number here\n" 418 | #endif 419 | 420 | //--------------------------------------------------------- 421 | // Special carrier modulator timer 422 | // 423 | #elif defined(IR_USE_TIMER_CMT) 424 | 425 | #define TIMER_RESET ({ \ 426 | uint8_t tmp __attribute__((unused)) = CMT_MSC; \ 427 | CMT_CMD2 = 30; \ 428 | }) 429 | 430 | #define TIMER_ENABLE_PWM do { \ 431 | CORE_PIN5_CONFIG = PORT_PCR_MUX(2) | PORT_PCR_DSE | PORT_PCR_SRE; \ 432 | } while(0) 433 | 434 | #define TIMER_DISABLE_PWM do { \ 435 | CORE_PIN5_CONFIG = PORT_PCR_MUX(1) | PORT_PCR_DSE | PORT_PCR_SRE; \ 436 | } while(0) 437 | 438 | #define TIMER_ENABLE_INTR NVIC_ENABLE_IRQ(IRQ_CMT) 439 | #define TIMER_DISABLE_INTR NVIC_DISABLE_IRQ(IRQ_CMT) 440 | #define TIMER_INTR_NAME cmt_isr 441 | 442 | //----------------- 443 | #ifdef ISR 444 | # undef ISR 445 | #endif 446 | #define ISR(f) void f(void) 447 | 448 | //----------------- 449 | #define CMT_PPS_DIV ((F_BUS + 7999999) / 8000000) 450 | #if F_BUS < 8000000 451 | #error IRremote requires at least 8 MHz on Teensy 3.x 452 | #endif 453 | 454 | //----------------- 455 | #define TIMER_CONFIG_KHZ(val) ({ \ 456 | SIM_SCGC4 |= SIM_SCGC4_CMT; \ 457 | SIM_SOPT2 |= SIM_SOPT2_PTD7PAD; \ 458 | CMT_PPS = CMT_PPS_DIV - 1; \ 459 | CMT_CGH1 = ((F_BUS / CMT_PPS_DIV / 3000) + ((val)/2)) / (val); \ 460 | CMT_CGL1 = ((F_BUS / CMT_PPS_DIV / 1500) + ((val)/2)) / (val); \ 461 | CMT_CMD1 = 0; \ 462 | CMT_CMD2 = 30; \ 463 | CMT_CMD3 = 0; \ 464 | CMT_CMD4 = 0; \ 465 | CMT_OC = 0x60; \ 466 | CMT_MSC = 0x01; \ 467 | }) 468 | 469 | #define TIMER_CONFIG_NORMAL() ({ \ 470 | SIM_SCGC4 |= SIM_SCGC4_CMT; \ 471 | CMT_PPS = CMT_PPS_DIV - 1; \ 472 | CMT_CGH1 = 1; \ 473 | CMT_CGL1 = 1; \ 474 | CMT_CMD1 = 0; \ 475 | CMT_CMD2 = 30; \ 476 | CMT_CMD3 = 0; \ 477 | CMT_CMD4 = (F_BUS / 160000 + CMT_PPS_DIV / 2) / CMT_PPS_DIV - 31; \ 478 | CMT_OC = 0; \ 479 | CMT_MSC = 0x03; \ 480 | }) 481 | 482 | #define TIMER_PWM_PIN 5 483 | 484 | // defines for TPM1 timer on Teensy-LC 485 | #elif defined(IR_USE_TIMER_TPM1) 486 | #define TIMER_RESET FTM1_SC |= FTM_SC_TOF; 487 | #define TIMER_ENABLE_PWM CORE_PIN16_CONFIG = PORT_PCR_MUX(3)|PORT_PCR_DSE|PORT_PCR_SRE 488 | #define TIMER_DISABLE_PWM CORE_PIN16_CONFIG = PORT_PCR_MUX(1)|PORT_PCR_SRE 489 | #define TIMER_ENABLE_INTR NVIC_ENABLE_IRQ(IRQ_FTM1) 490 | #define TIMER_DISABLE_INTR NVIC_DISABLE_IRQ(IRQ_FTM1) 491 | #define TIMER_INTR_NAME ftm1_isr 492 | #ifdef ISR 493 | #undef ISR 494 | #endif 495 | #define ISR(f) void f(void) 496 | #define TIMER_CONFIG_KHZ(val) ({ \ 497 | SIM_SCGC6 |= SIM_SCGC6_TPM1; \ 498 | FTM1_SC = 0; \ 499 | FTM1_CNT = 0; \ 500 | FTM1_MOD = (F_PLL/2000) / val - 1; \ 501 | FTM1_C0V = (F_PLL/6000) / val - 1; \ 502 | FTM1_SC = FTM_SC_CLKS(1) | FTM_SC_PS(0); \ 503 | }) 504 | #define TIMER_CONFIG_NORMAL() ({ \ 505 | SIM_SCGC6 |= SIM_SCGC6_TPM1; \ 506 | FTM1_SC = 0; \ 507 | FTM1_CNT = 0; \ 508 | FTM1_MOD = (F_PLL/40000) - 1; \ 509 | FTM1_C0V = 0; \ 510 | FTM1_SC = FTM_SC_CLKS(1) | FTM_SC_PS(0) | FTM_SC_TOF | FTM_SC_TOIE; \ 511 | }) 512 | #define TIMER_PWM_PIN 16 513 | 514 | // defines for timer_tiny0 (8 bits) 515 | #elif defined(IR_USE_TIMER_TINY0) 516 | #define TIMER_RESET 517 | #define TIMER_ENABLE_PWM (TCCR0A |= _BV(COM0B1)) 518 | #define TIMER_DISABLE_PWM (TCCR0A &= ~(_BV(COM0B1))) 519 | #define TIMER_ENABLE_INTR (TIMSK |= _BV(OCIE0A)) 520 | #define TIMER_DISABLE_INTR (TIMSK &= ~(_BV(OCIE0A))) 521 | #define TIMER_INTR_NAME TIMER0_COMPA_vect 522 | #define TIMER_CONFIG_KHZ(val) ({ \ 523 | const uint8_t pwmval = SYSCLOCK / 2000 / (val); \ 524 | TCCR0A = _BV(WGM00); \ 525 | TCCR0B = _BV(WGM02) | _BV(CS00); \ 526 | OCR0A = pwmval; \ 527 | OCR0B = pwmval / 3; \ 528 | }) 529 | #define TIMER_COUNT_TOP (SYSCLOCK * USECPERTICK / 1000000) 530 | #if (TIMER_COUNT_TOP < 256) 531 | #define TIMER_CONFIG_NORMAL() ({ \ 532 | TCCR0A = _BV(WGM01); \ 533 | TCCR0B = _BV(CS00); \ 534 | OCR0A = TIMER_COUNT_TOP; \ 535 | TCNT0 = 0; \ 536 | }) 537 | #else 538 | #define TIMER_CONFIG_NORMAL() ({ \ 539 | TCCR0A = _BV(WGM01); \ 540 | TCCR0B = _BV(CS01); \ 541 | OCR0A = TIMER_COUNT_TOP / 8; \ 542 | TCNT0 = 0; \ 543 | }) 544 | #endif 545 | 546 | #define TIMER_PWM_PIN 1 /* ATtiny85 */ 547 | 548 | //--------------------------------------------------------- 549 | // ESP32 (ESP8266 should likely be added here too) 550 | // 551 | 552 | // ESP32 has it own timer API and does not use these macros, but to avoid ifdef'ing 553 | // them out in the common code, they are defined to no-op. This allows the code to compile 554 | // (which it wouldn't otherwise) but irsend will not work until ESP32 specific code is written 555 | // for that -- merlin 556 | // As a warning, sending timing specific code from an ESP32 can be challenging if you need 100% 557 | // reliability because the arduino code may be interrupted and cause your sent waveform to be the 558 | // wrong length. This is specifically an issue for neopixels which require 800Khz resolution. 559 | // IR may just work as is with the common code since it's lower frequency, but if not, the other 560 | // way to do this on ESP32 is using the RMT built in driver like in this incomplete library below 561 | // https://github.com/ExploreEmbedded/ESP32_RMT 562 | #elif defined(IR_TIMER_USE_ESP32) 563 | #define TIMER_RESET 564 | #define TIMER_ENABLE_PWM 565 | #define TIMER_DISABLE_PWM Serial.println("IRsend not implemented for ESP32 yet"); 566 | #define TIMER_ENABLE_INTR 567 | #define TIMER_DISABLE_INTR 568 | #define TIMER_INTR_NAME 569 | 570 | //--------------------------------------------------------- 571 | // Unknown Timer 572 | // 573 | #else 574 | # error "Internal code configuration error, no known IR_USE_TIMER# defined\n" 575 | #endif 576 | 577 | #endif // ! boarddefs_h 578 | -------------------------------------------------------------------------------- /examples/Analytics/Decode/Decode.ino: -------------------------------------------------------------------------------- 1 | 2 | 3 | #include 4 | #define SSERIAL Serial 5 | 6 | DYIRDaikin irdaikin; 7 | void setup() 8 | { 9 | SSERIAL.begin(115200); 10 | delay(500); 11 | SSERIAL.println("Decode Demo Start!"); 12 | irdaikin.begin(); 13 | irdaikin.decodePin(2); 14 | } 15 | 16 | void loop() { 17 | if (irdaikin.decode() == 1) { 18 | irdaikin.description(); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /examples/Analytics/RecvPacket/RecvPacket.ino: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | DYIRDaikinRecv _irrecv; 4 | uint8_t irReceiveData[30] = {0}; 5 | #define SSERIAL Serial 6 | 7 | void setup() { 8 | SSERIAL.begin(115200); 9 | delay(2000); 10 | SSERIAL.println(); 11 | SSERIAL.println("Daikin Recv Packet Start"); 12 | _irrecv.begin(2,irReceiveData,30); 13 | 14 | } 15 | 16 | void loop() { 17 | _irrecv.dumpPackets(); 18 | } 19 | -------------------------------------------------------------------------------- /examples/Analytics/SendMark/SendMark.ino: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | //#define DYIRDAIKIN_SOFT_IR 5 | 6 | DYIRDaikinSend daikinSend; 7 | int isOn; 8 | 9 | void setup() 10 | { 11 | Serial.begin(115200); 12 | #ifdef DYIRDAIKIN_SOFT_IR 13 | daikinSend.begin(3); 14 | #else 15 | daikinSend.begin(); 16 | #endif 17 | delay(1000); 18 | Serial.println(); 19 | Serial.println("Start"); 20 | } 21 | 22 | void loop() { 23 | daikinSend.mark(1000); 24 | delay(1000); 25 | } 26 | -------------------------------------------------------------------------------- /examples/BRCPowerOnOff/BRCPowerOnOff.ino: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | 5 | DYIRDaikinBRC irdaikin; 6 | int isOn; 7 | 8 | void setup() 9 | { 10 | Serial.begin(115200); 11 | irdaikin.begin(); 12 | irdaikin.on(); 13 | irdaikin.setFan(0); 14 | irdaikin.setTemp(25); 15 | //----everything is ok and to execute send command----- 16 | irdaikin.sendCommand(); 17 | isOn = 0; 18 | } 19 | 20 | void loop() { 21 | while (Serial.available() > 0) { 22 | 23 | if (Serial.read() == '\n') { 24 | if (isOn == 0) { 25 | isOn = 1; 26 | irdaikin.off(); 27 | Serial.println("Turn Off"); 28 | } else { 29 | isOn = 0; 30 | irdaikin.on(); 31 | irdaikin.setFan(1); 32 | irdaikin.setTemp(22); 33 | Serial.println("Turn On"); 34 | } 35 | irdaikin.sendCommand(); 36 | Serial.println("Execute Command!"); 37 | } 38 | } 39 | } 40 | 41 | -------------------------------------------------------------------------------- /examples/Bridge/Bridge.ino: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | #define DYIRDAIKIN_SOFT_IR 5 | DYIRDaikin irdaikin; 6 | int isOn; 7 | 8 | void setup() 9 | { 10 | Serial.begin(115200); 11 | delay(500); 12 | Serial.println("Daikin Bridge Start!"); 13 | #ifdef DYIRDAIKIN_SOFT_IR 14 | irdaikin.begin(3); 15 | #else 16 | irdaikin.begin(); 17 | #endif 18 | irdaikin.decodePin(4); 19 | irdaikin.on(); 20 | irdaikin.setSwing_off(); 21 | irdaikin.setMode(1); 22 | irdaikin.setFan(4);//FAN speed to MAX 23 | irdaikin.setTemp(25); 24 | } 25 | 26 | void loop() { 27 | if (irdaikin.decode() == 1) { 28 | irdaikin.description(); 29 | delay(1000); 30 | irdaikin.sendCommand(); 31 | Serial.println("send command"); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /examples/LoopTest/LoopTest.ino: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | #define DYIRDAIKIN_SOFT_IR_1 5 | 6 | DYIRDaikin irdaikin; 7 | int isOn; 8 | 9 | void setup() 10 | { 11 | Serial.begin(115200); 12 | //#ifdef DYIRDAIKIN_SOFT_IR_1 13 | irdaikin.begin(3); 14 | //#else 15 | //irdaikin.begin(); 16 | //#endif 17 | irdaikin.on(); 18 | irdaikin.setSwing_off(); 19 | irdaikin.setMode(1); 20 | irdaikin.setFan(4);//FAN speed to MAX 21 | irdaikin.setTemp(25); 22 | //----everything is ok and to execute send command----- 23 | irdaikin.sendCommand(); 24 | isOn = 0; 25 | } 26 | 27 | void loop() { 28 | irdaikin.sendCommand(); 29 | Serial.println("Execute Command!"); 30 | delay(5000); 31 | } 32 | -------------------------------------------------------------------------------- /examples/PowerOnOff/PowerOnOff.ino: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | //#define DYIRDAIKIN_SOFT_IR 5 | 6 | DYIRDaikin irdaikin; 7 | int isOn; 8 | 9 | void setup() 10 | { 11 | Serial.begin(115200); 12 | #ifdef DYIRDAIKIN_SOFT_IR 13 | irdaikin.begin(3); 14 | #else 15 | irdaikin.begin(); 16 | #endif 17 | irdaikin.on(); 18 | irdaikin.setSwing_off(); 19 | irdaikin.setMode(1); 20 | irdaikin.setFan(4);//FAN speed to MAX 21 | irdaikin.setTemp(25); 22 | //----everything is ok and to execute send command----- 23 | irdaikin.sendCommand(); 24 | isOn = 0; 25 | } 26 | 27 | void loop() { 28 | while (Serial.available() > 0) { 29 | 30 | if (Serial.read() == '\n') { 31 | if (isOn == 0){ 32 | isOn = 1; 33 | irdaikin.off(); 34 | Serial.println("Turn Off"); 35 | }else{ 36 | isOn = 0; 37 | irdaikin.on(); 38 | Serial.println("Turn On"); 39 | } 40 | irdaikin.sendCommand(); 41 | Serial.println("Execute Command!"); 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /keywords.txt: -------------------------------------------------------------------------------- 1 | ####################################### 2 | # Syntax Coloring Map For IRDaikin ARC/BRC 3 | ####################################### 4 | 5 | ####################################### 6 | # Datatypes (KEYWORD1) 7 | ####################################### 8 | DYIRDaikin KEYWORD1 DYIRDaikin 9 | DYIRDaikinBRC KEYWORD1 DYIRDaikinBRC 10 | DYIRDaikinSend KEYWORD1 DYIRDaikinSend 11 | ####################################### 12 | # Methods and Functions (KEYWORD2) 13 | ####################################### 14 | decode KEYWORD2 15 | decodePin KEYWORD2 16 | daikin_on KEYWORD2 17 | daikin_off KEYWORD2 18 | daikin_setSwing_on KEYWORD2 19 | daikin_setSwing_off KEYWORD2 20 | daikin_setMode KEYWORD2 21 | daikin_setFan KEYWORD2 22 | daikin_setTemp KEYWORD2 23 | daikin_sendCommand KEYWORD2 24 | dump KEYWORD2 25 | setPin KEYWORD2 26 | ####################################### 27 | # Instances (KEYWORD2) 28 | ####################################### 29 | 30 | ####################################### 31 | # Constants (LITERAL1) 32 | ####################################### 33 | -------------------------------------------------------------------------------- /library.properties: -------------------------------------------------------------------------------- 1 | name=DY_Daikin 2 | version=1.2.0 3 | author=Danny 4 | maintainer=danny@35g.tw 5 | sentence= 6 | paragraph= 7 | category=Sensors 8 | url=https://github.com/danny-source/Arduino_DY_Daikin 9 | architectures=* 10 | --------------------------------------------------------------------------------