//####################################################################################################### //## This Plugin is only for use with the RFLink software package ## //## Plugin-03: Kaku (ARC) ## //####################################################################################################### /*********************************************************************************************\ * This plugin takes care of sending and receiving the ARC protocol known from Klik-Aan-Klik-Uit (KAKU) * transmitter, switch, PIR, door sensor etc. * Devices following the ARC protocol can often be recognized by their manual switch settings for * the unit and house code number. Like for example by code wheel, dip switch or mini switch. * * This plugin also works with the following devices: * Princeton PT2262 / MOSDESIGN M3EB / Domia Lite / Klik-Aan-Klik-Uit / Intertechno / Sartano 2606. * * Author : StuntTeam & Jonas Jespersen (Sartano) * Support : http://sourceforge.net/projects/rflink/ * License : This code is free for use in any open source project when this header is included. * License : This code is free for use in any open source project when this header is included. * Usage of any parts of this code in a commercial application is prohibited! *********************************************************************************************** * Address = A0..P16 according to KAKU adressing/notation *********************************************************************************************** * Het signaal bestaat drie soorten reeksen van vier pulsen, te weten: * 0 = T,3T,T,3T, 1 = T,3T,3T,T, short 0 = T,3T,T,T Hierbij is iedere pulse (T) 350us PWDM * * KAKU Supports: * on/off, waarbij de pulsreeks er als volgt uit ziet: 000x en x staat voor Off / On * all on/off, waarbij de pulsreeks er als volgt uit ziet: 001x en x staat voor All Off / All On *********************************************************************************************** * Brand Model Chipset Timing L/H * Intertechno ITK200 MDT10P61S 8/43 * Profile PN-47N SC5262 5/26-27 * Elro Home Comfort AB-600MA PT2262 7/29-30 6/30 6/31 * Eurodomest 972080 HS2303 * Elro Home Control AB-440 (Home Control) HX2262 * Elro Home Control AB-4xx (Home Control) HX2272 * Profile PN-44N SC2262 9/34 * ProMax RSL366T SC5262 11/41 10/54 11/54 ? * Phenix YC-4000S HX2262 * Flamingo FA500R 8/30 * Select Remote 1728029 HS2262 3/22 *********************************************************************************************** * POSSIBLE BIT VARIATIONS: (Note: Bit order is reversed -compared to order in the RF signal- in the description below and in the processing!!!) * ------------------------ ( real: 1111 0000 011 1 => reversed: 1 110 0000 1111) * ARC with 0 & F bits: * ------------------- * KAKU 1 110 0000 0000 * Intertechno ITK200 D CCC BBBB AAAA * A bit 0-3 = address 2^4 = 16 addresses * B bit 4-7 = device 2^4 = 16 devices * C bit 8-10 = always (110) ! (AND with 0x700 result must be 0x600) * D bit 11 = on/off command (1=on 0=off) * Timing: 8-9 /33-34 (low/high) * Pulses: 0101 and 0110 eg. bit state 0 and f * 1 110 0000 0000 A1 on * 0 110 0000 0000 A1 off * 1 110 0001 0000 A2 on * 0 110 0001 0000 A2 off * 1 110 0010 0000 A3 on * 0 110 0010 0000 A3 off * 1 110 0011 0000 A4 on * 0 110 0011 0000 A4 off * 1 110 0000 0000 itk200 on * 0 110 0000 0000 itk200 off * ------------------- * Perel 1 1111 1111 11 1 * A BBBB CCCC DD E * A bit 0 = on/off command * B bit 1-4 = system code 1111 each bit corresponds to a button number * C bit 5-8 = device / Unitcode 1111 each bit corresponds to a button number * D bit 9-10 = always '11' * E bit 11 = on/off command (1=on 0=off) * Timing: 8-9 /33-34 * Analyser: 362 / 1086 * Pulses: 0101 and 0110 eg. bit state 0 and f * 1 110 100 1110 1 1 on * 0 110 100 1110 0 1 off * 1 110 101 1110 1 2 on * 0 110 101 1110 0 2 off * 1 110 110 1110 1 3 on * 0 110 110 1110 0 3 off * ------------------- * Elro Home Easy 0 1 00001 10001 * Elro Home Control D C BBBBB AAAAA * Brennenstuhl A bit 0-4 = address 2^5 = 32 addresses * Comfort B bit 5-9 = device * C bit 10 = unknown (always 1?) * D bit 11 = on/off command (1=on 0=off) * Timing: 7-8-9 /29-30 * Pulses: 0101 and 0110 eg. bit state 0 and f * 1 1 10101 11000 I12 on * 0 1 10101 11000 I12 off * 1 1 10011 00000 A7 on * 0 1 10011 00000 A7 off * ------------------- * AB400R 0 1 11111 11111 * D C BBBBB AAAAA * A bit 0-4 = system code - each bit corresponds to a dip switch number (order 54321) * B bit 5-9 = device/unit code * C bit 10 = on/off command (reverse of D) * D bit 11 = on/off command * Timing: 8 /30 * Analyser: 330/990 * Pulses: 0101 and 0110 eg. bit state 0 and f * 10 11110 11110 A ON * 10 11101 11110 B ON * 10 11011 11110 C ON * 10 10111 11110 D ON * 01 11110 11110 A OFF * 01 11101 11110 B OFF * 01 11011 11110 C OFF * 01 10111 11110 D OFF * ------------------- * Sartano: 0 1 00001 10001 * Phenix YC-4000B D C BBBBB AAAAA * A bit 0-4 = address 2^5 = 32 addresses / Housecode * B bit 5-9 = device / Unitcode each bit corresponds to a button number * C bit 10 = off command (inverse command) * D bit 11 = on command * Timing: 11-12 /31-37 * Pulses: 0101 and 0110 eg. bit state 0 and f * 01 01000 00000 * ------------------- * ProMAX: 0 111 0000 0001 * D CCC BBBB AAAA * A bit 0-3 = address 2^5 = 32 addresses / Housecode * B bit 4-7 = device / Unitcode 11111 each bit corresponds to a button number * C bit 8-10 = Always 111 * D bit 11 = on command * Timing: 10-11 / 40-41 * Pulses: 0101 and 0110 eg. bit state 0 and f * 111111101110 1 ON * 111111011110 2 ON * 111110111110 3 ON * 111101111110 4 ON * 011111101110 1 OFF * 011111011110 2 OFF * 011110111110 3 OFF * 011101111110 4 OFF * ------------------- * ProFile: 0 110 0001 0001 * D CCC BBBB AAAA * A bit 0-3 = address 2^4 = 16 addresses / Housecode * B bit 4-7 = device / Unitcode 11111 each bit corresponds to a button number * C bit 8-10 = Always 110 * D bit 11 = on command * Timing: 9/34 * Pulses: 0101 and 0110 eg. bit state 0 and f * 111000000000 1 ON * 111000010000 2 ON * 111000100000 3 ON * 111000110000 4 ON * 011000000000 1 OFF * 011000010000 2 OFF * 011000100000 3 OFF * 011000110000 4 OFF * ------------------- * ProFile: * Everflourish 0 110 0001 0001 * EMW203 D CCC BBBB AAAA * A bit 0-3 = Button A/B/C/D * B bit 4-6 = Button 1/2/3 * C bit 7-10 = Always 1111 * D bit 11 = on/off command (on = tri-state) * Timing: 14/55 * Analyser: * Pulses: 0101, 1010 and 0110 eg. bit state 0, 1 and f * 211111101110 A1 on * 211111011110 A2 on * 211110111110 A3 on * 211111101101 B1 on * 211111011101 B2 on * 211110111101 B3 on * 011111101110 A1 off * 011111011110 A2 off * 011110111110 A3 off * 011111101101 B1 off * 011111011101 B2 off * 011110111101 B3 off * ------------------- * ------------------- * 0 111 0000 1 000 reverse: 000 1 0000 111 0 and EF1 = 0? * A BBB CCCC D EEE * SelectRemote A/C/E = always 0 0000 000 ! * Blokker: B bit 1-3 = device number * D bit 8 = on/off command * Timing: 0-1-2 /33-34 * Analyser: 232 / 692 * Pulses: 0101 and 1010 eg. bit state 0 and 1 * ------------------- * 1111 111111 11 * AAAA BBBBBB CC * Action: A bit 0-3 = address 2^4 = 16 addresses * Impuls B bit 4-9 = device * C bit 10-11= on/off command 10=on 01=off * ------------------- * 10100 00010 0 0 * AAAAA BBBBB C D * InterTechno A bit 0-4 = address 2^5 = 32 addresses * Düwi Terminal B bit 5-9 = device * Cogex C bit 10 = always 0 * D bit 11 = on/off command * ------------------- * 20;DB;DEBUG;Pulses=50;Pulses(uSec)=425,1050,250,1025,250,1025,250,1025,250,1025,250,1025,250,1025,250,1025,250,1050,250,1025,250,1025,250,1025,250,1025,250,1025,250,1025,250,1025,250,1050,250,1025,250,1025,950,300,250,1050,950,300,250,1025,950,300,250; * * KAKU Doorbell 010111101111 * 20;07;DEBUG;Pulses=50;Pulses(uSec)=300,950,250,950,250,950,950,275,250,950,250,950,250,950,950,275,250,950,950,275,250,950,950,250,250,950,950,275,250,950,250,950,250,950,950,275,250,950,950,250,250,950,950,275,250,950,950,250,250; * 20;09;DEBUG;Pulses=50;Pulses(uSec)=3675,950,250,950,250,950,950,250,250,950,250,950,250,950,950,275,250,950,950,250,250,950,950,275,250,950,950,250,250,950,250,950,250,950,950,250,250,950,950,275,250,950,950,275,250,950,950,275,250; * HE842 * 20;03;DEBUG;Pulses=50;Pulses(uSec)=270,870,840,240,210,870,840,240,210,870,210,870,210,870,840,240,210,870,210,870,210,870,210,870,210,870,210,870,210,870,840,240,210,870,210,870,210,870,840,240,210,870,840,240,210,870,210,870,210,6990; * 360/1380 12/46 * 20;54;DEBUG;Pulses=50;Pulses(uSec)=1410,390,1350,360,1350,360,1380,360,1350,360,1380,360,1380,360,1380,360,1350,360,1350,360,1350,360,1380,360,1380,360,1380,360,1350,360,1380,360,1350,360,1350,360,390,1350,390,1350,390,1320,390,1320,420,1320,420,1320,390,6990; \*********************************************************************************************/ #define KAKU_CodeLength 12 // number of data bits #define KAKU_R 300/RAWSIGNAL_SAMPLE_RATE //360 // 300 // 370? 350 us #define KAKU_PULSEMID 510/RAWSIGNAL_SAMPLE_RATE // (17) 510 = KAKU_R*2 not sufficient! #ifdef PLUGIN_003 boolean Plugin_003(byte function, char *string) { if (RawSignal.Number!=(KAKU_CodeLength*4)+2) return false; // conventionele KAKU bestaat altijd uit 12 data bits plus stop. Ongelijk, dan geen KAKU! if (RawSignal.Pulses[0]==15) return true; // Home Easy, skip KAKU if (RawSignal.Pulses[0]==63) return false; // No need to test, packet for plugin 63 if (RawSignal.Pulses[0]==19) return false; // No need to test, packet for plugin 19 // ------------------------------------------- int i,j; boolean error=false; unsigned long bitstream=0L; // to store a 12 bit code (ARC type) unsigned long bitstream2=0L; // to store a 24 bit code (Extended ARC type) byte tricount=0; // ------------------------------------------- byte command=0; // ON/OFF/DIM/BRIGHT byte group=0; // flags group command byte housecode=0; // 0x40 + 1 to 16? (41-5a?) byte unitcode=0; // 1 to 16 // ------------------------------------------- int PTLow=22; // Pulse Time - lowest found value (22 = a pulse duration of 550) int PTHigh=22; // Pulse Time - highest found value byte signaltype=0; // bit map: bit 0 = 0 bit 1 = f bit 2 = 0/1 (PT2262) // meaning: byte value 3 = kaku (bit 0/f) 5=PT2262 7=tristate 0/1/f byte devicetype=0; // 0=Kaku 5=Impuls 7=Perel // ------------------------------------------- // ------------------------------------------- // ========================================================================== j=KAKU_PULSEMID; // set MID value j--; if (RawSignal.Pulses[0]==33) { // If device is "Impuls" RawSignal.Pulses[0]=0; // Unset Impuls conversion indicator j=KAKU_R; // Set new (LOWER!) MID value devicetype=5; // Indicate Impuls device } // ------------------------------------------- if (RawSignal.Pulses[49] > j) return false; // Last pulse has to be low! Otherwise we are not dealing with an ARC signal // ========================================================================== // TIMING MEASUREMENT, this will find the shortest and longest pulse within the RF packet // ========================================================================== for (i=2;i PTHigh) { // longest pulse? PTHigh=RawSignal.Pulses[i]; // new value } } // ------------------------------------------- // TIMING MEASUREMENT to devicetype if (devicetype != 5) { // Dont do the timing check for Impuls, it is already identified at this point if( ((PTLow==7)||(PTLow==8)) && ((PTHigh ==30) || (PTHigh ==31) ) ) devicetype=4; // ELRO AB400 if( ((PTLow==9)||(PTLow==10)) && ((PTHigh==36)||(PTHigh==37)||((PTHigh >=40)&&(PTHigh <=42))) ) devicetype=1; // ELRO AB600 else if( ((PTLow==10)||(PTLow == 11)) && ((PTHigh >=40)&&(PTHigh <=42)) ) devicetype=2; // Profile PR44N / Promax rsl366t else if( (PTLow==13) && ((PTHigh >=32)&&(PTHigh <=34)) ) devicetype=3; // Profile PR47N else if( ((PTLow >=11)&&(PTLow <=12)) && ((PTHigh >=31)&&(PTHigh <=37)) ) devicetype=4; // Sartano else if( ((PTLow==12)||(PTLow==13)) && ((PTHigh==45)||(PTHigh==46)) ) devicetype=4; // Philips SBC else if( (PTLow <=3) && ((PTHigh==22)||(PTHigh==23)) ) devicetype=5; // Philips SBC //else //if( (PTLow == 8 || PTLow == 9) && (PTHigh == 33 || PTHigh == 34) ) devicetype=7; // Perel st=0,dt=7 } //sprintf(pbuffer, "ST=%d DT=%d %d/%d",signaltype,devicetype,PTLow,PTHigh); //Serial.println( pbuffer ); // ========================================================================== // Turn pulses into bits // ------------------------------------------- for (i=0; ij && RawSignal.Pulses[4*i+3]j) { // 0101 bitstream=(bitstream >> 1); // bit '0' bitstream2=(bitstream2 << 2); // bit '0' written as '00' signaltype=signaltype|1; // bit '0' present in signal '0001' } else if (RawSignal.Pulses[4*i+1]j && RawSignal.Pulses[4*i+3]>j && RawSignal.Pulses[4*i+4]> 1 | (1 << (KAKU_CodeLength-1))); // bit f (1) bitstream2=(bitstream2 << 2) | 2; // bit 'f' written as '10' // DONT CHANGE signal type to tri-state to keep EMW200 in KAKU mode } else { bitstream=(bitstream >> 1 | (1 << (KAKU_CodeLength-1))); // bit f (1) bitstream2=(bitstream2 << 2) | 2; // bit 'f' written as '10' signaltype=signaltype|2; // bit 'f' present in signal '0010' } } else if (RawSignal.Pulses[4*i+1]j && RawSignal.Pulses[4*i+3]> 1); // Short 0, Group command on 2nd bit. (NOT USED?!) bitstream2=(bitstream2 << 2) | 3; // bit 'short' written as '11' group=1; } else if (RawSignal.Pulses[4*i+1]>j && RawSignal.Pulses[4*i+2]j && RawSignal.Pulses[4*i+4]> 1); // bit 1 (stored as 0) (IMPULS REMOTE) } else { if (i==11) { // last bit seems to cause trouble every now and then..?! bitstream=(bitstream >> 1); // bit 1 (stored as 0) (IMPULS REMOTE) } else { devicetype=6; bitstream=(bitstream >> 1 | (1 << (KAKU_CodeLength-1))); // bit f (1) } } } else { // ------------------------------------------- // following are signal patches to fix bad transmission/receptions // ------------------------------------------- if (i==0) { // are we dealing with a RTK/AB600 device? then the first bit is sometimes mistakenly seen as 1101 bitstream2=(bitstream2 << 2); // bit 0 if (RawSignal.Pulses[4*i+1]>j && RawSignal.Pulses[4*i+2]>j && RawSignal.Pulses[4*i+3]j) { // 1101 bitstream=(bitstream >> 1); // 0, treat as 0101 eg 0 bit } else { error=true; signaltype=signaltype|8; } } else { error=true; signaltype=signaltype|8; } } // bad signal } //================================================================================== // Sort out devices based on signal type and timing measurements // ------------------------------------------- //sprintf(pbuffer, "ST=%d DT=%d [%d]",signaltype,devicetype, error); //Serial.println( pbuffer ); //Serial.println(bitstream,BIN); //Serial.println(bitstream2,BIN); // ------------------------------------------- // END OF TIMING MEASUREMENTS // ========================================================================== if (error==true) { // Error means that a pattern other than 0101/0110 was found return false; // This usually means we are dealing with a semi-compatible device } // that might have more states than used by ARC if ((signaltype != 0x03) && (signaltype != 0x05) && (signaltype != 0x07)) return false; //================================================================================== // Prevent repeating signals from showing up //================================================================================== //if( (SignalHash!=SignalHashPrevious) || ((RepeatingTimer+500)millis())&&(SignalCRC != bitstream2)) ) { // not seen the RF packet recently if (signaltype == 0x07) { if (((RepeatingTimer+1000)>millis())&&(SignalCRC != bitstream2)) { return true; // skip tristate after normal arc } } //Serial.print("KAKU PREV:"); //Serial.println(SignalHashPrevious); if ((SignalHashPrevious==14) && ((RepeatingTimer+2000)>millis()) ) { SignalHash=14; return true; // SignalHash 14 = HomeEasy, eg. cant switch KAKU after HE for 2 seconds } if ((SignalHashPrevious==11) && ((RepeatingTimer+2000)>millis()) ) { SignalHash=11; return true; // SignalHash 11 = FA500, eg. cant switch KAKU after FA500 for 2 seconds } SignalCRC=bitstream2; // store RF packet identifier } else { // already seen the RF packet recently return true; } //================================================================================== // Determine signal type to sort out the various houdecode/unitcode/button bits and on/off command bits //================================================================================== if (signaltype != 0x07) { if ((bitstream&0x700)!=0x600) { // valid but not real KAKU devicetype=4; } // ------------------------------------------- if (devicetype == 4) { // Sartano // ---------------------------------- // Sartano housecode = ((bitstream) & 0x0000001FL); // .......11111b unitcode = (((bitstream) & 0x000003E0L) >> 5); // ..1111100000b housecode = ~housecode; // Sartano housecode is 5 bit ('A' - '`') housecode &= 0x0000001FL; // Translate housecode so that all jumpers off = 'A' and all jumpers on = '`' housecode += 0x41; switch(unitcode) { // Translate unit code into button number 1 - 5 case 0x1E: // E=1110 unitcode = 1; break; case 0x1D: // D=1101 unitcode = 2; break; case 0x1B: // B=1011 unitcode = 3; break; case 0x17: // 7=0111 unitcode = 4; break; case 0x0F: // f=1111 unitcode = 5; break; default: //Serial.print("Sartano:"); devicetype=3; // invalid for Sartano, fall back break; } if (devicetype == 4) { // Sartano if ( ((bitstream >> 10) & 0x03) == 2) { command = 1; // On } else if ( ((bitstream >> 10) & 0x03) == 1){ command = 0;// Off } } } else // ------------------------------------------- if (devicetype == 5) { // IMPULS housecode = ((bitstream) & 0x0000000FL); // ........1111b unitcode = (((bitstream) & 0x000003F0L) >> 4); // ..1111110000b housecode = ~housecode; // Impuls housecode is 4 bit ('A' - 'P') housecode &= 0x0000000FL; // Translate housecode so that all jumpers off = 'A' and all jumpers on = 'P' housecode += 0x41; unitcode = ~unitcode; // Impuls unitcode is 5 bit unitcode &= 0x0000001FL; // Translate unitcode so that all jumpers off = '1' and all jumpers on = '64' if ( ((bitstream >> 10) & 0x03) == 2) { command = 0; // Off } else if ( ((bitstream >> 10) & 0x03) == 1){ command = 1;// On } } else // ------------------------------------------- if (devicetype == 6) { // Blokker/SelectRemote // ---------------------------------- if ( ((bitstream)&0xef1) != 0) return false; // Not a valid bitstream housecode = ((bitstream) & 0x0000000EL); // Isolate housecode housecode = housecode >> 1; // shift right 1 bit housecode = (~housecode)&0x07; // invert bits housecode += 0x41; // add 'A' unitcode = 0; if ( ((bitstream >> 8) & 0x01) == 1) { command = 1; // On } else { command = 0;// Off } // ---------------------------------- // Sartano } else // ------------------------------------------- if (devicetype != 4) { // KAKU (and some compatibles for now) // ---------------------------------- if ((bitstream&0x700)!=0x600) { // valid but not real KAKU housecode=(((bitstream) &0x0f) +0x41); unitcode=((((bitstream) &0xf0) >> 4)+1); devicetype=1; } else { if ((bitstream&0x600)!=0x600) { //Serial.println("Kaku 0/1 error"); return false; // use two static bits as checksum } //bitstream=(bitstream)&0xffe; // kill bit to ensure Perel works -> actually kills code wheel letter B housecode=(((bitstream) &0x0f) +0x41); unitcode=((((bitstream) &0xf0) >> 4)+1); // ---------------------------------- } if ( ((bitstream >> 11) & 0x01) == 1) { command=1; // ON } else { command=0; // OFF } } } // ========================================================================== // Output // ---------------------------------- sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number Serial.print( pbuffer ); // ---------------------------------- if (signaltype == 0x03) { // '0011' bits indicate bits 0 and f are used in the signal if (devicetype < 4) { // KAKU (and some compatibles for now) Serial.print(F("Kaku;")); // Label } else { if (devicetype == 4) { // AB440R and Sartano Serial.print(F("AB400D;")); // Label } else if (devicetype == 5) { // Impuls Serial.print(F("Impuls;")); // Label } else { Serial.print(F("Sartano;")); // Others } } } else if (signaltype == 0x05) { // '0101' bits indicate bits 0 and 1 are used in the signal if (devicetype == 5) { // KAKU (and some compatibles for now) Serial.print(F("Impuls;")); // Label } else { Serial.print(F("PT2262;")); // Label } } else if (signaltype == 0x07) { // '0111' bits indicate bits 0, f and 1 are used in the signal (tri-state) Serial.print(F("TriState;")); // Label } // ---------------------------------- if (signaltype == 0x07) { // '0111' bits indicate bits 0, f and 1 are used in the signal (tri-state) sprintf(pbuffer, "ID=%06lx;",((bitstream2)>>4)&0xffffff) ; // ID Serial.print( pbuffer ); housecode=(bitstream2)&0x03; unitcode=((((bitstream2)>>2)&0x03)^0x03)^housecode; //command=((bitstream2)&1)^1; << ^1 reverses lidl light command=((bitstream2)&3); // 00 01 10 0 1 f if (command > 1) command=1; // 0 stays 0 (OFF), 1 and f become 1 (ON) } else { sprintf(pbuffer, "ID=%02x;", housecode); // ID Serial.print( pbuffer ); } sprintf(pbuffer, "SWITCH=%d;", unitcode); Serial.print( pbuffer ); Serial.print(F("CMD=")); if (group==1) Serial.print(F("ALL")); if ( command == 1 ) { Serial.print(F("ON;")); } else { Serial.print(F("OFF;")); } Serial.println(); // ---------------------------------- RawSignal.Repeats=true; // suppress repeats of the same RF packet RawSignal.Number=0; return true; } #endif //PLUGIN_003 #ifdef PLUGIN_TX_003 void Arc_Send(unsigned long address); // sends 0 and float void NArc_Send(unsigned long bitstream); // sends 0 and 1 void TriState_Send(unsigned long bitstream); // sends 0, 1 and float boolean PluginTX_003(byte function, char *string) { boolean success=false; unsigned long bitstream=0L; byte command=0; uint32_t housecode = 0; uint32_t unitcode = 0; byte Home=0; // KAKU home A..P byte Address=0; // KAKU Address 1..16 byte c=0; byte x=0; // ========================================================================== //10;Kaku;00004d;1;OFF; //10;Kaku;00004f;e;ON; //10;Kaku;000050;10;ON; //10;Kaku;000049;b;ON; //012345678901234567890 // ========================================================================== if (strncasecmp(InputBuffer_Serial+3,"KAKU;",5) == 0) { // KAKU Command eg. Kaku;A1;On if (InputBuffer_Serial[14] != ';') return false; x=15; // character pointer InputBuffer_Serial[10]=0x30; InputBuffer_Serial[11]=0x78; // Get home from hexadecimal value InputBuffer_Serial[14]=0x00; // Get home from hexadecimal value Home=str2int(InputBuffer_Serial+10); // KAKU home A is intern 0 if (Home < 0x51) // take care of upper/lower case Home=Home - 'A'; else if (Home < 0x71) // take care of upper/lower case Home=Home - 'a'; else { return false; // invalid value } while((c=InputBuffer_Serial[x++])!=';'){ // Address: 1 to 16/32 if(c>='0' && c<='9'){Address=Address*10;Address=Address+c-'0';} if(c>='a' && c<='f'){Address=Address+(c-'a'+10);} // 31? if(c>='A' && c<='F'){Address=Address+(c-'A'+10);} // 51? } //if (Address==0) { // group command is given: 0=all // command=2; // Set 2nd bit for group. // bitstream=Home; //} else { // bitstream= Home | ((Address-1)<<4); //} bitstream= Home | ((Address-1)<<4); command |= str2cmd(InputBuffer_Serial+x)==VALUE_ON; // ON/OFF command bitstream = bitstream | (0x600 | ((command & 1) << 11)); // create the bitstream //Serial.println(bitstream); Arc_Send(bitstream); success=true; // --------------- END KAKU SEND ------------ } else // ========================================================================== //10;AB400D;00004d;1;OFF; //012345678901234567890 // ========================================================================== if (strncasecmp(InputBuffer_Serial+3,"AB400D;",7) == 0) { // KAKU Command eg. Kaku;A1;On if (InputBuffer_Serial[16] != ';') return false; x=17; // character pointer InputBuffer_Serial[12]=0x30; InputBuffer_Serial[13]=0x78; // Get home from hexadecimal value InputBuffer_Serial[16]=0x00; // Get home from hexadecimal value Home=str2int(InputBuffer_Serial+12); // KAKU home A is intern 0 if (Home < 0x61) // take care of upper/lower case Home=Home - 'A'; else if (Home < 0x81) // take care of upper/lower case Home=Home - 'a'; else { return false; // invalid value } while((c=InputBuffer_Serial[x++])!=';'){ // Address: 1 to 16/32 if(c>='0' && c<='9'){Address=Address*10;Address=Address+c-'0';} } command = str2cmd(InputBuffer_Serial+x)==VALUE_ON; // ON/OFF command housecode = ~Home; housecode &= 0x0000001FL; unitcode=Address; if ((unitcode >= 1) && (unitcode <= 5) ) { bitstream = housecode & 0x0000001FL; if (unitcode == 1) bitstream |= 0x000003C0L; else if (unitcode == 2) bitstream |= 0x000003A0L; else if (unitcode == 3) bitstream |= 0x00000360L; else if (unitcode == 4) bitstream |= 0x000002E0L; else if (unitcode == 5) bitstream |= 0x000001E0L; if (command) bitstream |= 0x00000800L; else bitstream |= 0x00000400L; } //Serial.println(bitstream); Arc_Send(bitstream); success=true; } else // --------------- END SARTANO SEND ------------ // ========================================================================== //10;PT2262;000041;1;OFF; //012345678901234567890 // ========================================================================== if (strncasecmp(InputBuffer_Serial+3,"PT2262;",7) == 0) { // KAKU Command eg. Kaku;A1;On if (InputBuffer_Serial[16] != ';') return false; x=17; // character pointer InputBuffer_Serial[12]=0x30; InputBuffer_Serial[13]=0x78; // Get home from hexadecimal value InputBuffer_Serial[16]=0x00; // Get home from hexadecimal value Home=str2int(InputBuffer_Serial+12); // KAKU home A is intern 0 if (Home < 0x61) // take care of upper/lower case Home=Home - 'A'; else if (Home < 0x81) // take care of upper/lower case Home=Home - 'a'; else { return false; // invalid value } while((c=InputBuffer_Serial[x++])!=';'){ // Address: 1 to 16/32 if(c>='0' && c<='9'){Address=Address*10;Address=Address+c-'0';} } // reconstruct bitstream reversed order so that most right bit can be send first command = str2cmd(InputBuffer_Serial+x)==VALUE_ON; // ON/OFF command housecode = ~Home; housecode &= 0x00000007L; housecode=(housecode)<<1; if (command) bitstream |= 0x00000100L; NArc_Send(bitstream); // send 24 bits tristate signal (0/1/f) success=true; } else // --------------- END Select Remote SEND ------------ // ========================================================================== //10;TriState;00004d;1;OFF; //10;TriState;08000a;2;OFF; 20;1B;TriState;ID=08000a;SWITCH=2;CMD=OFF; //10;TriState;0a6980;2;OFF; //01234567890123456789012 // ========================================================================== if (strncasecmp(InputBuffer_Serial+3,"TriState;",9) == 0) { // KAKU Command eg. Kaku;A1;On if (InputBuffer_Serial[18] != ';') return false; x=19; // character pointer InputBuffer_Serial[10]=0x30; InputBuffer_Serial[11]=0x78; // Get home from hexadecimal value InputBuffer_Serial[18]=0x00; // Get home from hexadecimal value bitstream=str2int(InputBuffer_Serial+10); // KAKU home A is intern 0 bitstream=(bitstream<<4); // 11^00^01=10 11^10^11=01 11^11^00=00 while((c=InputBuffer_Serial[x++])!=';'){ // Address: 0/1/2 if(c>='0' && c<='9'){Address=Address*10;Address=Address+c-'0';} } Address=(Address)&0x03; // only use 3 bits command = str2cmd(InputBuffer_Serial+x); // ON/OFF command if (command==VALUE_ON) { // on if (Address==0x0) bitstream |= 0x0000000bL; // 0011 if (Address==0x1) bitstream |= 0x0000000cL; // 1011 if (Address==0x2) bitstream |= 0x00000001L; // 0001 } else { // off if (Address==0x0) bitstream |= 0x0000000cL; // 1100 if (Address==0x1) bitstream |= 0x0000000eL; // 1110 if (Address==0x2) bitstream |= 0x00000004L; // 0100 } TriState_Send(bitstream); success=true; } else // --------------- END TRISTATE SEND ------------ // ========================================================================== //10;Impuls;00004d;1;OFF; //012345678901234567890 // ========================================================================== if (strncasecmp(InputBuffer_Serial+3,"Impuls;",7) == 0) { // KAKU Command eg. Kaku;A1;On if (InputBuffer_Serial[16] != ';') return false; x=17; // character pointer InputBuffer_Serial[12]=0x30; InputBuffer_Serial[13]=0x78; // Get home from hexadecimal value InputBuffer_Serial[16]=0x00; // Get home from hexadecimal value Home=str2int(InputBuffer_Serial+12); // KAKU home A is intern 0 if (Home < 0x61) // take care of upper/lower case Home=Home - 'A'; else if (Home < 0x81) // take care of upper/lower case Home=Home - 'a'; else { return false; // invalid value } while((c=InputBuffer_Serial[x++])!=';'){ // Address: 1 to 16/32 if(c>='0' && c<='9'){Address=Address*10;Address=Address+c-'0';} } command = str2cmd(InputBuffer_Serial+x)==VALUE_ON; // ON/OFF command housecode = ~Home; housecode &= 0x0000001FL; unitcode=Address; if ((unitcode >= 1) && (unitcode <= 5) ) { bitstream = housecode & 0x0000001FL; if (unitcode == 1) bitstream |= 0x000003C0L; else if (unitcode == 2) bitstream |= 0x000003A0L; else if (unitcode == 3) bitstream |= 0x00000360L; else if (unitcode == 4) bitstream |= 0x000002E0L; else if (unitcode == 5) bitstream |= 0x000001E0L; if (command) bitstream |= 0x00000800L; else bitstream |= 0x00000400L; } TriState_Send(bitstream); success=true; } return success; } //#define KAKU_T 390 //420 // 370 // 370? 350 us //#define Sartano_T 300 //360 // 300 // 300 uS void Arc_Send(unsigned long bitstream) { int fpulse = 360; // Pulse width in microseconds int fretrans = 8; // Number of code retransmissions uint32_t fdatabit; uint32_t fdatamask = 0x00000001; uint32_t fsendbuff; digitalWrite(PIN_RF_RX_VCC,LOW); // Turn off power to the RF receiver digitalWrite(PIN_RF_TX_VCC,HIGH); // Enable the 433Mhz transmitter delayMicroseconds(TRANSMITTER_STABLE_DELAY); // short delay to let the transmitter become stable (Note: Aurel RTX MID needs 500µS/0,5ms) for (int nRepeat = 0; nRepeat <= fretrans; nRepeat++) { fsendbuff = bitstream; // Send command for (int i = 0; i < 12; i++) { // Arc packet is 12 bits // read data bit fdatabit = fsendbuff & fdatamask; // Get most right bit fsendbuff = (fsendbuff >> 1); // Shift right // PT2262 data can be 0, 1 or float. Only 0 and float is used by regular ARC if (fdatabit != fdatamask) { // Write 0 digitalWrite(PIN_RF_TX_DATA, HIGH); delayMicroseconds(fpulse * 1); digitalWrite(PIN_RF_TX_DATA, LOW); delayMicroseconds(fpulse * 3); digitalWrite(PIN_RF_TX_DATA, HIGH); delayMicroseconds(fpulse * 1); digitalWrite(PIN_RF_TX_DATA, LOW); delayMicroseconds(fpulse * 3); } else { // Write float digitalWrite(PIN_RF_TX_DATA, HIGH); delayMicroseconds(fpulse * 1); digitalWrite(PIN_RF_TX_DATA, LOW); delayMicroseconds(fpulse * 3); digitalWrite(PIN_RF_TX_DATA, HIGH); delayMicroseconds(fpulse * 3); digitalWrite(PIN_RF_TX_DATA, LOW); delayMicroseconds(fpulse * 1); } } // Send sync bit digitalWrite(PIN_RF_TX_DATA, HIGH); delayMicroseconds(fpulse * 1); digitalWrite(PIN_RF_TX_DATA, LOW); // and lower the signal delayMicroseconds(fpulse * 31); } delayMicroseconds(TRANSMITTER_STABLE_DELAY); // short delay to let the transmitter become stable (Note: Aurel RTX MID needs 500µS/0,5ms) digitalWrite(PIN_RF_TX_VCC,LOW); // Turn the 433Mhz transmitter off digitalWrite(PIN_RF_RX_VCC,HIGH); // Turn the 433Mhz receiver on RFLinkHW(); } void NArc_Send(unsigned long bitstream) { int fpulse = 190; // Pulse width in microseconds int fretrans = 7; // Number of code retransmissions uint32_t fdatabit; uint32_t fdatamask = 0x00000001; uint32_t fsendbuff; digitalWrite(PIN_RF_RX_VCC,LOW); // Turn off power to the RF receiver digitalWrite(PIN_RF_TX_VCC,HIGH); // Enable the 433Mhz transmitter delayMicroseconds(TRANSMITTER_STABLE_DELAY); // short delay to let the transmitter become stable (Note: Aurel RTX MID needs 500µS/0,5ms) for (int nRepeat = 0; nRepeat <= fretrans; nRepeat++) { fsendbuff = bitstream; // Send command for (int i = 0; i < 12; i++) { // Arc packet is 12 bits // read data bit fdatabit = fsendbuff & fdatamask; // Get most right bit fsendbuff = (fsendbuff >> 1); // Shift right // PT2262 data can be 0, 1 or float. Only 0 and float is used by regular ARC if (fdatabit != fdatamask) { // Write 0 digitalWrite(PIN_RF_TX_DATA, HIGH); delayMicroseconds(fpulse * 1); digitalWrite(PIN_RF_TX_DATA, LOW); delayMicroseconds(fpulse * 3); digitalWrite(PIN_RF_TX_DATA, HIGH); delayMicroseconds(fpulse * 1); digitalWrite(PIN_RF_TX_DATA, LOW); delayMicroseconds(fpulse * 3); } else { // Write 1 digitalWrite(PIN_RF_TX_DATA, HIGH); delayMicroseconds(fpulse * 3); digitalWrite(PIN_RF_TX_DATA, LOW); delayMicroseconds(fpulse * 1); digitalWrite(PIN_RF_TX_DATA, HIGH); delayMicroseconds(fpulse * 3); digitalWrite(PIN_RF_TX_DATA, LOW); delayMicroseconds(fpulse * 1); } } // Send sync bit digitalWrite(PIN_RF_TX_DATA, HIGH); delayMicroseconds(fpulse * 1); digitalWrite(PIN_RF_TX_DATA, LOW); // and lower the signal delayMicroseconds(fpulse * 31); } delayMicroseconds(TRANSMITTER_STABLE_DELAY); // short delay to let the transmitter become stable (Note: Aurel RTX MID needs 500µS/0,5ms) digitalWrite(PIN_RF_TX_VCC,LOW); // Turn thew 433Mhz transmitter off digitalWrite(PIN_RF_RX_VCC,HIGH); // Turn the 433Mhz receiver on RFLinkHW(); } void TriState_Send(unsigned long bitstream) { int fpulse = 360; // Pulse width in microseconds int fretrans = 8; // Number of code retransmissions uint32_t fdatabit; uint32_t fdatamask = 0x00000003; uint32_t fsendbuff; digitalWrite(PIN_RF_RX_VCC,LOW); // Turn off power to the RF receiver digitalWrite(PIN_RF_TX_VCC,HIGH); // Enable the 433Mhz transmitter delayMicroseconds(TRANSMITTER_STABLE_DELAY); // short delay to let the transmitter become stable (Note: Aurel RTX MID needs 500µS/0,5ms) // reverse data bits (2 by 2) for (unsigned short i=0; i<12; i++) { // reverse data bits (12 times 2 bits = 24 bits in total) fsendbuff<<=2; fsendbuff|=(bitstream & B11); bitstream>>=2; } bitstream=fsendbuff; // store result for (int nRepeat = 0; nRepeat <= fretrans; nRepeat++) { fsendbuff = bitstream; // Send command for (int i = 0; i < 12; i++) { // 12 times 2 bits = 24 bits in total // read data bit fdatabit = fsendbuff & fdatamask; // Get most right 2 bits fsendbuff = (fsendbuff >> 2); // Shift right // data can be 0, 1 or float. if (fdatabit == 0) { // Write 0 digitalWrite(PIN_RF_TX_DATA, HIGH); delayMicroseconds(fpulse); digitalWrite(PIN_RF_TX_DATA, LOW); delayMicroseconds(fpulse * 3); digitalWrite(PIN_RF_TX_DATA, HIGH); delayMicroseconds(fpulse); digitalWrite(PIN_RF_TX_DATA, LOW); delayMicroseconds(fpulse * 3); } else if (fdatabit == 1) { // Write 1 digitalWrite(PIN_RF_TX_DATA, HIGH); delayMicroseconds(fpulse * 3); digitalWrite(PIN_RF_TX_DATA, LOW); delayMicroseconds(fpulse * 1); digitalWrite(PIN_RF_TX_DATA, HIGH); delayMicroseconds(fpulse * 3); digitalWrite(PIN_RF_TX_DATA, LOW); delayMicroseconds(fpulse * 1); } else { // Write float digitalWrite(PIN_RF_TX_DATA, HIGH); delayMicroseconds(fpulse * 1); digitalWrite(PIN_RF_TX_DATA, LOW); delayMicroseconds(fpulse * 3); digitalWrite(PIN_RF_TX_DATA, HIGH); delayMicroseconds(fpulse * 3); digitalWrite(PIN_RF_TX_DATA, LOW); delayMicroseconds(fpulse * 1); } } // Send sync bit digitalWrite(PIN_RF_TX_DATA, HIGH); delayMicroseconds(fpulse * 1); digitalWrite(PIN_RF_TX_DATA, LOW); // and lower the signal delayMicroseconds(fpulse * 31); } delayMicroseconds(TRANSMITTER_STABLE_DELAY); // short delay to let the transmitter become stable (Note: Aurel RTX MID needs 500µS/0,5ms) digitalWrite(PIN_RF_TX_VCC,LOW); // Turn thew 433Mhz transmitter off digitalWrite(PIN_RF_RX_VCC,HIGH); // Turn the 433Mhz receiver on RFLinkHW(); } #endif //PLUGIN_TX_003