diff --git a/README_nl.md b/README_nl.md new file mode 100644 index 0000000..dd6c867 --- /dev/null +++ b/README_nl.md @@ -0,0 +1,24 @@ +# HackCube-Special +

PICTURE logo

+

+💰 Aankopen | +📖 Project Documentatie | +🌐 Community
+
+

+## HackCube-Special Wat is het? + +### HackCube-Special is een draagbaar radioplatform voor hardwaredetectie om op meerdere radiofrequentiebanden reverse-analyse van omringende RF-signalen te vergemakkelijken. + +## Wat kan het doen. + +### Op dit moment kunt u het kaartnummer van de `EM41XX` (125 KhHz) lezen, u kunt het kaartnummer van de` / `blast` uit de EM41XX-serie` simuleren ', maar dit onderdeel is niet bijzonder stabiel. Vervalsing van het signaal 'autobanddruksensor', de omgekeerde signaaldemodulatie van de 'auto-afstandsbediening' (HCS-chip), kan `sniffing / zenden / stralen 'aanvallen op de' vaste code '(224X, 226X) uitvoeren en kan Intelligente interferentie `/` gewelddadige interferentie in de `` sub1G`-band van het RF-signaal, kan het apparaat van de `nRF24l01` sniffen en maken. En kan het` HID`-apparaat (`toetsenbord`,` muis`) pseudo-creëren `wifi`-methode om` playload` in te voeren. + +## Gebruik +> 1. Schakel de HackCube Special -stroomknop in. Statuslampje geeft normaal blauw weer +> +> 2.Zoek en link naar draadloze hotspot "HackCubeSpecial_XX: XX: XX", wachtwoord: "hackcube" +> +> 3.Verbind met een internet browser http://192.168.5.1 +> + diff --git a/Software/ATmega32U4_nl/ATmega32U4_nl.ino b/Software/ATmega32U4_nl/ATmega32U4_nl.ino new file mode 100644 index 0000000..0ebdb81 --- /dev/null +++ b/Software/ATmega32U4_nl/ATmega32U4_nl.ino @@ -0,0 +1,84 @@ +/* + @@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + @@@@@@@@@ @@@@ + @@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@ + @@@@@ @@@@@@@@@@@@@@@@@@@@@@@ @@@@@ + @@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@ + @@@@@ @@@@@ @@@@@@@@@@@@@@@@@@ @@@@@ + @@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@ + @@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@ + @@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@ + @@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@ + @@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@ + @@@@@ @@@@@@@@@@@@@@@@@@@@ @@@@@ + @@@@@ @@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@ + @@@@@ @@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@ + @@@@@ @@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@ + @@@@ @@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@ + @@@@ @@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@ + @@@@ @@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@ + @@@@@ @@@@@@@@@@@@@@@@@ @@@@@@@@@@@ + @@@@@ @@@@@@@@@@@@@@@@@ @@@@@@@@@ + @@@@@ @@@@@@@ + @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + @@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + _ _ _ + | | | | | | + | |__ __ _ ___ | | __ ___ _ _ | |__ ___ + | '_ \ / _` | / __|| |/ // __|| | | || '_ \ / _ \ + | | | || (_| || (__ | <| (__ | |_| || |_) || __/ + |_| |_| \__,_| \___||_|\_\\___| \__,_||_.__/ \___| + + Author: mobier + Email: vxxwej@gmail.com + Git repository: https://github.com/UnicornTeam/HackCube-Special +*/ + +long freq_cc1101 = 315000000; //Stel de CC1101-standaard luisterfrequentie in +//long freq_cc1101 = 434000000; //Stel de CC1101-standaard luisterfrequentie in +int rf_class = 1;//Stel de RF-luistermodus in op vaste code +#define Cube_PRINT Serial1 +#define Print_Time 350 +unsigned long SerialLastTime; +String Cube_PRINT_data; +#include "HackCube.h" +#include "rf.h" +#include "hid.h" +#include "nfc.h" +#include "SerialCommunication.h" +HackCube hc; +void setup() { + Cube_PRINT.begin(9600);//Stel de communicatie pin in met ESP8266 + delay(2000); + hc.pinSetup();//Initialisatie module pin + delay(100); + Cube_PRINT.println("Cubemini Runing..."); + cc1101_config();//Configureer de CC1101-module om standaard te luisteren naar de frequentie in de variabele freq_cc1101 + delay(4); + cc1101.PrintConfig();//Uitgang CC 1101 sleutelregisters + mySwitch.enableReceive(1);//Stel de mySwitch-onderbrekingspin in om het vaste codesignaal te ontvangen + //rf_class=2; + //freq_cc1101=433920000; + //RF433_Setup_rollcode();//Rolling code CC1101 register configuratie + //cc1101_config(); + //Hackradio.enableReceive(RF315_att);//Stel de onderbrekingspin in om het rolling codesignaal te ontvangen + //rf24l01_SnifferSetup();//Initialiseer de nRF24L01-module en druk de registergegevens af + //NFC_Switch("off"); + +} +void loop() { + + //rf24Sniffer();//Polling nRF24L01 bufferregister om gegevens te ontvangen + SnifferEM4100();//Decodeer kaartnummergegevens door de OUT-uitgangspen van de EM4095 te pollen + AttackEM4100();//Simuleer/vernietig kaarten uit de EM4100-serie volgens de instructies + SerialCommunication();//Via de seriële poort ESP8266 Communicatie interactiegegevens + if (rf_class == 1) { + SnifferFixedCode();//Vaste codegegevens sniffen + } else if (rf_class == 2) { + SnifferRollcode();//Rollende codegegevens sniffen + } +} + + + diff --git a/Software/ATmega32U4_nl/ATmega32U4_nl.ino.micro.hex b/Software/ATmega32U4_nl/ATmega32U4_nl.ino.micro.hex new file mode 100644 index 0000000..4178047 --- /dev/null +++ b/Software/ATmega32U4_nl/ATmega32U4_nl.ino.micro.hex @@ -0,0 +1,1749 @@ +:100000000C945B010C940E190C94E7180C94C01816 +:100010000C9499180C9483010C9483010C9472181D +:100020000C9483010C9483010C949D1B0C94681C0C +:100030000C9483010C9483010C9483010C94830130 +:100040000C9483010C9483010C9483010C94830120 +:100050000C9483010C9483010C9483010C94281854 +:100060000C9483010C9432160C940C160C9483019E +:100070000C9483010C9483010C9483010C948301F0 +:100080000C9483010C9483010C9483010C948301E0 +:100090000C9483010C9483010C9483010C948301D0 +:1000A0000C9483010C9483010C9483017C167F16BD +:1000B0006E1672167816A016A016A016831687164E +:1000C0008B1691169516A0169B16000000002300B3 +:1000D000260029002C002F00040404040403040556 +:1000E00002020202040302020202060606060606D5 +:1000F00004040202020404040802011040804010BB +:10010000204080408008020401804020100201103D +:100110008010204040200000000200090F00000372 +:100120000401000C000000000000000000000000BE +:10013000000000000005010906A10185020507195C +:10014000E029E715002501750195088102950175E3 +:10015000088103950675081500256505071900290E +:10016000658100C05E01011F01030301008A0201D5 +:100170000A010202010064001E47040B0906007C0C +:100180000101060103030100F401060E0102020150 +:1001900000C201170101020201019600023E0106A0 +:1001A00006010000000000240027002A002D003076 +:1001B0000000000000250028002B002E0031000860 +:1001C0000B0002020201000904000001020200000B +:1001D0000524001001052401010104240206052460 +:1001E0000600010705810310004009040100020A0E +:1001F00000000007050202400000070583024000DE +:10020000000403090412010002EF020140412337F8 +:100210008000010102030141726475696E6F204C18 +:100220004C430041726475696E6F204D6963726F53 +:100230000000000000000000002A2B280000000041 +:1002400000000000000000000000000000000000AE +:10025000002C9EB4A0A1A2A434A6A7A5AE362D372B +:1002600038271E1F20212223242526B333B62EB77C +:10027000B89F8485868788898A8B8C8D8E8F909194 +:1002800092939495969798999A9B9C9D2F3130A321 +:10029000AD350405060708090A0B0C0D0E0F1011E9 +:1002A00012131415161718191A1B1C1DAFB1B0B56F +:1002B00000001F2D0B2D11241FBECFEFDAE0DEBF93 +:1002C000CDBF14E0A0E0B1E0EAE0FAE602C005909C +:1002D0000D92A432B107D9F728E0A4E2B4E001C03E +:1002E0001D92A532B207E1F711E0CAE5D1E004C0E2 +:1002F0002197FE010E949933C935D107C9F70E94A1 +:100300004F280C94F8340C9400002F923F924F9297 +:100310005F926F927F928F929F92AF92BF92CF9295 +:10032000DF92EF92FF920F931F93CF93DF93CDB79E +:10033000DEB7E9970FB6F894DEBF0FBECDBF24E05D +:1003400030E041E050E06EE875E0CE0101960E9499 +:10035000571B6FE771E0CE0101960E94331A182FE8 +:10036000CE0101960E940B1B112309F4A7C063E87C +:1003700071E0CE0101960E94421BCE0101960E94BF +:100380002F118C01CE0101960E940B1B012BC9F489 +:1003900068E871E080E594E00E94E21563E886E594 +:1003A00095E00E949C276CE686E595E00E949C27DC +:1003B00068EE73E080E090E00E9432170E94760EB3 +:1003C0004EC06DE871E0CE0101960E94421BCE0145 +:1003D00001960E942F118C01CE0101960E940B1BE9 +:1003E000012B09F042C064E886E595E00E949C2755 +:1003F00062E886E595E00E949C2764E786E595E043 +:100400000E949C2768EC70E080E090E00E94321728 +:100410000E94760E6CED75E080E090E00E9432174D +:100420006CEC86E595E00E949C276CE271E080E030 +:1004300090E00E9432170E94760E6CE271E080E03C +:1004400090E00E94321762E971E086E595E00E9433 +:10045000F61564E670E080E090E00E94321760EBF1 +:1004600086E595E00E94062821C060E070E08EE8F5 +:1004700095E00E94211A2CE132E0DC012C932091BE +:1004800092053091930545E050E06EE875E0CE01AD +:1004900001960E94571BBE016F5F7F4F86E595E076 +:1004A0000E940F15CE0101960E940B1B6AE971E0B4 +:1004B00080E594E00E94E2150C940C0E23E030E0FD +:1004C00041E050E06EE875E0CE0101960E94571BB6 +:1004D0006EE971E0CE0101960E94331A182FCE0109 +:1004E00001960E940B1B112309F47AC761EA71E09F +:1004F000CE0101960E94421BCE0101960E942F114F +:100500008C01CE0101960E940B1B101611060CF0F7 +:10051000E1C065EA71E0CE0101960E94421BCE0166 +:1005200001960E942F118C016BEA71E0CE014B966F +:100530000E94421BCE014B960E942F11AC014A5FD4 +:100540005F4F98016EE875E0CE0189960E94571BB7 +:10055000CE014B960E940B1BCE0101960E940B1BF5 +:1005600061EB71E0CE0189960E94331A882309F469 +:100570006EC067EB71E0CE014B960E94421BCE012C +:100580004B960E942F118C016EEB71E0CE01839689 +:100590000E94421BCE0183960E942F11AC014A5F3C +:1005A0005F4F98016EE875E0CE0101960E94571BDF +:1005B0004AE050E060E070E089819A810E94672EF5 +:1005C00060932A0470932B0480932C0490932D0441 +:1005D000CE0101960E940B1BCE0183960E940B1B3D +:1005E000CE014B960E940B1B009192051091930532 +:1005F00068EB71E0CE014B960E94421BCE014B96F8 +:100600000E942F11AC014A5F5F4F98016EE875E0C0 +:10061000CE0101960E94571B4AE050E060E070E076 +:1006200089819A810E94672E609326047093270423 +:100630008093280490932904CE0101960E940B1BFD +:10064000CE014B960E940B1B81E090E03AC064EC17 +:1006500071E0CE0189960E94331A8823C1F100917E +:1006600092051091930566EA71E0CE014B960E94C7 +:10067000421BCE014B960E942F11AC014B5F5F4F86 +:1006800098016EE875E0CE0101960E94571B4AE082 +:1006900050E060E070E089819A810E94672E60934B +:1006A0000201709303018093040190930501CE0130 +:1006B00001960E940B1BCE014B960E940B1B82E001 +:1006C00090E090932504809324040E94B320CE01EF +:1006D000899631C569EC71E0CE0101960E94421BFA +:1006E000CE0101960E942F118C01CE0101960E942D +:1006F0000B1B101611060CF0BBC1FE0131966F01E9 +:100700000AE010E0E12CF12C809192059091930584 +:100710000817190708F085C0B8016F5F7F4F8EE892 +:1007200095E00E94211ADC016C91CE014B960E944B +:10073000101BB8018EE895E00E94211AFC0160812F +:10074000CE0189960E94101BBE01675D7F4FCE01CE +:1007500083960E94281BBE01655E7F4FCE01839663 +:100760000E94991ABC01CE018F960E94281BCE01CF +:1007700083960E940B1BCE0189960E940B1BCE0113 +:100780004B960E940B1B40E150E060E070E08FA5AB +:1007900098A90E94672E5601D6016C93B5E0EB161E +:1007A000F104A1F44AE050E060E070E08FA598A960 +:1007B0000E94672E0E9447312DEC3CEC4CE450E443 +:1007C0000E9484310E9456336E830EC0E6E0EE161E +:1007D000F10451F44AE050E060E070E08FA598A980 +:1007E0000E94672E695C6F836EE073E080E594E0A1 +:1007F0000E94F615FFEFCF1ADF0AD5014C9150E0A9 +:1008000060E070E020E180E594E00E943215BFEFE7 +:10081000EB1AFB0ACE018F960E940B1B0E5F1F4F37 +:1008200073CF6EEC71E080E594E00E94E2156CE11C +:1008300072E08EE895E00E94BB1A85E190E090930B +:1008400076058093750510922E0461E00E94D11602 +:100850000E94211060E082E00E94D11664E070E006 +:1008600080E090E00E9432170E94EC0F69E280E085 +:100870000E94870F6EE281E00E94870F66E082E0AF +:100880000E94870F67E483E00E94870F65E086E09F +:100890000E94870F64E087E00E94870F60E388E092 +:1008A0000E94870F61E983ED0E94D10F80917E0540 +:1008B000882331F060E089E00E94870F10927E0566 +:1008C00080917B05882331F060E08AE00E94870FE9 +:1008D00010927B0566E08BE00E94870F60E08CE061 +:1008E0000E94870F61E28DE00E94870F62E68EE032 +:1008F0000E94870F66E78FE00E94870F10927A05AB +:1009000068EF80E10E94870F6BE981E10E94870F09 +:1009100063E382E10E94870F62E283E10E94870F16 +:1009200068EF84E10E94870F60E085E10E94870FF5 +:1009300067E086E10E94870F60E387E10E94870FEE +:1009400068E188E10E94870F66E189E10E94870FD4 +:100950006CE68AE10E94870F63E08BE10E94870FBB +:1009600060E48CE10E94870F61E98DE10E94870FAE +:1009700067E88EE10E94870F6BE68FE10E94870F88 +:100980006BEF80E20E94870F66E581E20E94870F8D +:1009900061E182E20E94870F69EE83E20E94870F85 +:1009A0006AE284E20E94870F60E085E20E94870F7E +:1009B0006FE186E20E94870F61E487E20E94870F61 +:1009C00060E088E20E94870F69E589E20E94870F54 +:1009D0006FE78AE20E94870F6FE38BE20E94870F26 +:1009E00061E88CE20E94870F65E38DE20E94870F29 +:1009F0006BE08EE20E94870F0E94B50F60910101AB +:100A0000809100010E94D10F68E87BE28DED99E1B1 +:100A10000E942B2064E087E00E94870F68E088E155 +:100A20000E94870F63E082E10E94870F65E385E102 +:100A30000E94870F64E670E080E090E00E94321729 +:100A400083E30E94A10FCE0101960E94FD1F64E680 +:100A500070E080E090E00E943217CE0101960E9483 +:100A6000FD1F64E670E080E090E00E94321730C124 +:100A700066ED71E0CE0101960E94421BCE01019607 +:100A80000E942F118C01CE0101960E940B1B1016A3 +:100A900011060CF0C7C16FED71E0CE0101960E9406 +:100AA000421BCE0101960E942F118C01CE010196AE +:100AB0000E940B1B101611060CF00DC168EE71E0C0 +:100AC000CE014B960E94421BCE014B960E942F11E5 +:100AD0008C0166EA71E0CE0183960E94421BCE0132 +:100AE00083960E942F11AC014B5F5F4F98016EE817 +:100AF00075E0CE0101960E94571B4AE050E060E08D +:100B000070E089819A810E94672E6B017C01CE0181 +:100B100001960E940B1BCE0183960E940B1BCE01F7 +:100B20004B960E940B1B00919205109193056DE569 +:100B300073E0CE014B960E94421BCE014B960E9461 +:100B40002F11AC014B5F5F4F98016EE875E0CE014D +:100B500001960E94571B40E150E060E070E08981FF +:100B60009A810E94672E2B013C01CE0101960E94C2 +:100B70000B1BCE014B960E940B1BEBE3CE16E1E064 +:100B8000DE06E9F485E190E09093760580937505A3 +:100B90000E9438106FEF8FEF0E94D10F60EC74E865 +:100BA00086EC92E10E942B2064E087E00E94870F90 +:100BB00085E30E94A10F6DE080E00E94870F62E054 +:100BC00070E080E090E00E94321775E0A72EB12C13 +:100BD000E3E28E2EEAE09E2EF3E72F2EF4E03F2E86 +:100BE00061E084E10E94A11683EC94E10197F1F7A2 +:100BF00060E084E10E94A116C4010197F1F709E0C9 +:100C000010E061E084E10E94A116C4010197F1F7B0 +:100C100060E084E10E94A1168FE095E00197F1F772 +:100C20000150110971F70FE010E001501109D301D3 +:100C3000C201002E04C0B695A795979587950A9492 +:100C4000D2F761E080FF0CC084E10E94A116C401CC +:100C50000197F1F760E084E10E94A116C1010DC087 +:100C600084E10E94A1168BEB93E00197F1F760E01D +:100C700084E10E94A1168BEE9AE00197F1F701152D +:100C8000110599F6F1E0AF1AB10809F0A9CF6EEE9F +:100C900071E080E594E00E94F61562E072E080E584 +:100CA00094E00E94F615B701A601662777272AE08F +:100CB00080E594E00E94321568E072E080E594E0FF +:100CC0000E94F61540E150E0C301B2010E945E0FA0 +:100CD0000E948E20A1C721E130E04EE050E06EE896 +:100CE00075E0CE0101960E94571B4AE050E060E09B +:100CF00070E089819A810E94672E2B013C01CE0110 +:100D000001960E940B1B23E130E042E150E06EE8C7 +:100D100075E0CE0101960E94571B40E150E060E073 +:100D200070E089819A810E94672E6B017C018B01A2 +:100D3000CE0101960E940B1B2091920530919305E4 +:100D400044E150E06EE875E0CE0101960E94571B29 +:100D500040E150E060E070E089819A810E94672E56 +:100D60004B015C01CE0101960E940B1B2BE3421646 +:100D700021E052066104710419F40E946D2009C03B +:100D800031EB431631E053066104710411F40E9403 +:100D9000502068E0262E312CA801C501B4010E9424 +:100DA000A11F69E070E080E090E00E94321781E0CE +:100DB000281A310889F76FE072E080E594E00E941C +:100DC000F61562E072E080E594E00E94F6152AE0F4 +:100DD00030E0B301A20180E594E00E947B1564E459 +:100DE00072E080E594E00E94F615A601DD0C660B2A +:100DF000770B20E180E594E00E94321569E072E013 +:100E000080E594E00E94F61520E1B501A40180E59B +:100E100094E00E9432156AE172E080E594E00E945D +:100E20001D1556CF6DE172E0CE0101960E94421B66 +:100E3000CE0101960E942F118C01CE0101960E94D5 +:100E40000B1B101611060CF079C164E272E0CE01A2 +:100E500001960E94421BCE0101960E942F118C0127 +:100E600066EA71E0CE014B960E94421BCE014B9682 +:100E70000E942F11AC014B5F5F4F98016EE875E047 +:100E8000CE018F960E94571BCE014B960E940B1BE2 +:100E9000CE0101960E940B1B6BE272E0CE0101961F +:100EA0000E94421BCE0101960E942F118C0165E227 +:100EB00072E0CE014B960E94421BCE014B960E94DF +:100EC0002F11AC014A5F5F4F98016EE875E0CE01CB +:100ED00089960E94571BCE014B960E940B1BCE0198 +:100EE00001960E940B1B60E372E0CE0101960E9406 +:100EF000421BCE0101960E942F118C016CE272E020 +:100F0000CE014B960E94421BCE014B960E942F11A0 +:100F1000AC014C5F5F4F98016EE875E0CE0183969F +:100F20000E94571BCE014B960E940B1BCE010196CF +:100F30000E940B1B009192051091930561E372E0F2 +:100F4000CE0101960E94421BCE0101960E942F11F4 +:100F5000AC014B5F5F4F98016EE875E0CE014B9698 +:100F60000E94571BCE0101960E940B1B4AE050E0E5 +:100F700060E070E08FA598A90E94672E4B015C018C +:100F800040E150E060E070E089A59AA50E94672EDC +:100F90006B017C0140E150E060E070E08BA19CA11E +:100FA0000E94672E6DAB7EAB8FAB98AF40E150E0F7 +:100FB00060E070E08B8D9C8D0E94672E2B013C01C0 +:100FC0008B018DA99EA9AFA9B8AD0196A11DB11D38 +:100FD0008DAB9EABAFABB8AF9BE3891691E09906A2 +:100FE000A104B10419F40E946D2012C0A1EB8A166D +:100FF000A1E09A06A104B10419F40E94502008C08F +:101000002AE030E0B501A4018DEE94E00E947B154A +:1010100066E372E08DEE94E00E94F6152AE0B701D7 +:10102000A6018DEE94E00E9432156DE372E08DEE24 +:1010300094E00E94F6152AE04DA95EA96FA978AD4B +:101040008DEE94E00E94321563E472E08DEE94E040 +:101050000E94F6154AE050E0B2018DEE94E00E9445 +:10106000C915460157014DA85EA86FA878AC4C1869 +:101070005D086E087F088DA99EA9AFA9B8AD881636 +:101080009906AA06BB06D0F558E0252E312CA801FA +:10109000C501B4010E94A11F6CE070E080E090E007 +:1010A0000E943217B1E02B1A310889F760E570E031 +:1010B00080E090E00E943217EFEF8E1A9E0AAE0A8F +:1010C000BE0A6AE472E080E594E00E94F615A5018C +:1010D00094012C193D094E095F09A4E6B0E00E9475 +:1010E0009332A30192010E947432CA01B9014AE00D +:1010F00050E080E594E00E94C915BDCF80E594E002 +:101100000E94A7131816190634F40E948E2010921C +:101110002504109224040E948E20CE014B960E943A +:101120000B1BCE0183960E940B1BCE0189960E9459 +:101130000B1BCE018F960E940B1B6EC569E572E0FA +:10114000CE0101960E94421BCE0101960E942F11F2 +:101150008C01CE0101960E940B1B101611060CF09B +:1011600055C08091920590919305892B81F0009153 +:101170008E0510918F056DE070E0C8010E94C334A8 +:10118000009729F0DC01A01BB10B8D0102C00FEF0D +:101190001FEF60E672E0CE014B960E94421BCE012B +:1011A0004B960E942F11AC01495F5F4F98016EE88A +:1011B00075E0CE0101960E94571B61E772E0CE01F7 +:1011C00001960E94331A882359F060E088E00E945B +:1011D000A11667E672E080E594E00E94E21524C360 +:1011E0006FE772E0CE0101960E94331A882309F45A +:1011F0001BC361E088E00E94A11665E772E080E50C +:1012000094E00E94E2150E948E200EC362E872E014 +:10121000CE0101960E94421BCE0101960E942F1121 +:101220008C01CE0101960E940B1B101611060CF0CA +:10123000F3C468E872E0CE0101960E94421BCE0121 +:1012400001960E942F118C01CE0101960E940B1B6A +:10125000101611060CF0BBC065EA71E0CE010196D4 +:101260000E94421BCE0101960E942F118C016BEA55 +:1012700071E0CE014B960E94421BCE014B960E941C +:101280002F11AC014A5F5F4F98016EE875E0CE0107 +:1012900083960E94571BCE014B960E940B1BCE01DA +:1012A00001960E940B1B009192051091930566EA2E +:1012B00071E0CE014B960E94421BCE014B960E94DC +:1012C0002F11AC014B5F5F4F98016EE875E0CE01C6 +:1012D00001960E94571B4AE050E060E070E089816F +:1012E0009A810E94672E6093060170930701809394 +:1012F000080190930901CE0101960E940B1BCE01BB +:101300004B960E940B1B6BE972E0CE0183960E9404 +:10131000331A882331F101E010E010930B010093A0 +:101320000A01E99881E994E190930F0180930E01FD +:1013300086E30E94A10F60910601709107018091E0 +:101340000801909109010E942B2084E30E94A10FC3 +:101350001093800500937F050E9414116FE872E0DE +:101360002FC061EA72E0CE0183960E94331A88236F +:1013700059F182E090E090930B0180930A01E99883 +:1013800081E994E190930F0180930E0186E30E941E +:10139000A10F609106017091070180910801909161 +:1013A00009010E942B2084E30E94A10F81E090E0BC +:1013B00090936B0580936A050E94430F68EA72E080 +:1013C00080E594E00E94E215CE018396B4CE6BEBEB +:1013D00072E0CE0101960E94421BCE010196ABCE77 +:1013E00024E030E041E050E06EE875E0CE01019687 +:1013F0000E94571B64EC72E0CE0101960E94331AE2 +:10140000182FCE0101960E940B1B112309F4EDC386 +:1014100020E130E046E050E06EE875E0CE01019654 +:101420000E94571B68EC72E0CE0101960E94331AAD +:10143000182FCE0101960E940B1B112309F48CC0BA +:1014400081E090E0909333048093320468EE71E081 +:10145000CE014B960E94421BCE014B960E942F114B +:101460008C0163ED72E0CE0183960E94421BCE0197 +:1014700083960E942F11AC014D5F5F4F98016EE87B +:1014800075E0CE0101960E94571B89819A810E94C6 +:10149000792F90933D0480933C04CE0101960E94E5 +:1014A0000B1BCE0183960E940B1BCE014B960E9414 +:1014B0000B1B009192051091930569EE71E0CE012E +:1014C0004B960E94421BCE014B960E942F11AC01FD +:1014D0004B5F5F4F98016EE875E0CE0101960E9468 +:1014E000571B4AE050E060E070E089819A810E94D9 +:1014F000672E60933E0470933F0480934004909362 +:101500004104CE0101960E940B1BCE014B960E9416 +:101510000B1B60E073E080E594E00E94F6154091BB +:101520003C0450913D04052E000C660B770B2AE01D +:1015300030E080E594E00E947B156DEE72E080E57E +:1015400094E00E94F61560913E0470913F048091F2 +:1015500040049091410401C12CE030E046E050E0AD +:101560006EE875E0CE0101960E94571B66ED72E0B1 +:10157000CE0101960E94331A182FCE0101960E94C7 +:101580000B1B112309F4EEC082E090E0909333042A +:101590008093320464E272E0CE014B960E94421BBB +:1015A000CE014B960E942F118C0163ED72E0CE01AB +:1015B00083960E94421BCE0183960E942F11AC019C +:1015C0004D5F5F4F98016EE875E0CE0101960E9475 +:1015D000571B89819A810E94792F90933D048093B3 +:1015E0003C04CE0101960E940B1BCE0183960E9403 +:1015F0000B1BCE014B960E940B1B6BE272E0CE01DF +:101600004B960E94421BCE014B960E942F118C01DB +:1016100065E272E0CE0183960E94421BCE01839662 +:101620000E942F11AC014A5F5F4F98016EE875E090 +:10163000CE0101960E94571B4AE050E060E070E046 +:1016400089819A810E94672E6093340470933504D7 +:101650008093360490933704CE0101960E940B1BB1 +:10166000CE0183960E940B1BCE014B960E940B1B52 +:1016700000919205109193056CE272E0CE014B96B9 +:101680000E94421BCE014B960E942F11AC014C5F71 +:101690005F4F98016EE875E0CE0101960E94571BDE +:1016A0004AE050E060E070E089819A810E94672EF4 +:1016B000609338047093390480933A0490933B0408 +:1016C000CE0101960E940B1BCE014B960E940B1B74 +:1016D0008091340490913504A0913604B091370480 +:1016E00080933E0490933F04A0934004B093410440 +:1016F00060E073E080E594E00E94F61540913C04C0 +:1017000050913D04052E000C660B770B2AE030E06B +:1017100080E594E00E947B156DED72E080E594E039 +:101720000E94F615409134045091350460913604BE +:10173000709137042AE080E594E00E94321568EE4B +:1017400072E080E594E00E94F61560913804709193 +:10175000390480913A0490913B044AE050E00E94A1 +:101760005E0F5AC22CE030E046E050E06EE875E0D3 +:10177000CE0101960E94571B61EF72E0CE010196E7 +:101780000E94331A182FCE0101960E940B1B1123C1 +:1017900009F451C08091920590919305892B81F0B5 +:1017A00000918E0510918F056DE070E0C8010E94D8 +:1017B000C334009729F0FC01E01BF10B8F0102C03C +:1017C0000FEF1FEF60E672E0CE014B960E94421BC6 +:1017D000CE014B960E942F11AC01495F5F4F9801DB +:1017E0006EE875E0CE0101960E94571B61E772E03A +:1017F000CE0101960E94331A882331F061E086E021 +:101800000E94A11661E00DC06FE772E0CE01019663 +:101810000E94331A882341F060E086E00E94A116FE +:1018200060E089E00E94A116CE0101960E940B1B88 +:10183000CE014B9680CC68EF72E0CE0101960E94FB +:10184000421BCE0101960E942F118C01CE01019600 +:101850000E940B1B101611060CF0DEC168EE71E041 +:10186000CE014B960E94421BCE014B960E942F1137 +:101870008C0163ED72E0CE0183960E94421BCE0183 +:1018800083960E942F11AC014D5F5F4F98016EE867 +:1018900075E0CE0101960E94571B89819A810E94B2 +:1018A000792F90933D0480933C04CE0101960E94D1 +:1018B0000B1BCE0183960E940B1BCE014B960E9400 +:1018C0000B1B009192051091930569EE71E0CE011A +:1018D0004B960E94421BCE014B960E942F11AC01E9 +:1018E0004B5F5F4F98016EE875E0CE0101960E9454 +:1018F000571B4AE050E060E070E089819A810E94C5 +:10190000672E60933E0470933F048093400490934D +:101910004104CE0101960E940B1BCE014B960E9402 +:101920000B1B6EEF72E080E594E00E94F61540918B +:101930003C0450913D04052E000C660B770B2AE009 +:1019400030E080E594E00E947B156DEE72E080E56A +:1019500094E00E94F61560913E0470913F048091DE +:101960004004909141044AE050E00E945E0FC09014 +:101970003E04D0903F04E0904004F0904104009178 +:101980003C0410913D0488E0E3E3F1E0DE015B9666 +:1019900001900D928A95E1F71FA618AA19AA1AAA12 +:1019A00080E490E8A4E1B0E089A79AA7ABA7BCA720 +:1019B00060E089E00E94A11664E270E080E090E0BF +:1019C0000E94321740E062E0CE014B960E94840EE6 +:1019D00060E170E080E090E00E94321747E061E053 +:1019E000CE018F960E94840E61E270E080E090E06C +:1019F0000E94321740E061E0CE0189960E94840E79 +:101A000060E170E080E090E00E943217C801807FC2 +:101A1000992724E0959587952A95E1F79A838983FC +:101A20000F7011271C830B83FE01359620E030E0F8 +:101A30004FE0842E912CA12CB12CA901445E5F4F64 +:101A4000D501C401042E04C0880F991FAA1FBB1F13 +:101A50000A94D2F78C219D21AE21BF2104C0B695F6 +:101A6000A795979587954A95D2F78193919324509E +:101A70003109203E8FEF380701F7CE0101960E9411 +:101A80006F113C01812C912CB0E0A0E01DAA19AE91 +:101A9000212C512C80E8382E44244A94F301808173 +:101AA0003181F2E06F0E711C282F932F990F990B43 +:101AB000740182E3E80EF11C492F592F692F792F09 +:101AC000892F0E2D0E949F3359016A017B018C01E1 +:101AD0002B2F3A2F4DA959AD622D752D832D942DA5 +:101AE0000E94D633B22FA32F4DAB59AF262E572EBF +:101AF000382E492E95E0891A9108E9EC8E16EFEF01 +:101B00009E0661F62B2F3A2F622D752D832D942D75 +:101B100000E20E94BA332BA33CA34DA35EA39D0118 +:101B20009DA989AD39832A839B838C8341E061E041 +:101B3000CE0183960E94840E60E170E080E090E028 +:101B40000E94321742E061E0CE0101960E94840EAD +:101B500060E170E080E090E00E94321761E089E08F +:101B60000E94A11665E870E080E090E00E943217C4 +:101B700060E089E00E94A11665E870E080E090E0F6 +:101B80000E94321761E089E00E94A11661E086E0C0 +:101B90000E94A11664E670E080E090E00E94321797 +:101BA00060E089E00E94A11660E086E00E94A11634 +:101BB00064E670E080E090E00E94321761E089E026 +:101BC0000E94A11661E086E00E94A11664E670E022 +:101BD00080E090E00E94321760E089E00E94A11648 +:101BE00060E086E00E94A11617C064E073E080E523 +:101BF00094E00E94F61560E070E08EE895E00E94A7 +:101C0000211ADC016C91062E000C770B40E150E0AC +:101C100080E594E00E94C9156CE172E08EE895E0E1 +:101C20000E94BB1AE9960FB6F894DEBF0FBECDBF77 +:101C3000DF91CF911F910F91FF90EF90DF90CF90A8 +:101C4000BF90AF909F908F907F906F905F904F90DC +:101C50003F902F900895CF93C62FBC018DEE94E056 +:101C60000E94F6156BE073E08DEE94E00E94F6158D +:101C70008C2F0E94BB12482F50E060E070E020E102 +:101C80008DEE94E00E9432156AE172E08DEE94E0F0 +:101C90000E941D15CF91089560E086E00E94A11674 +:101CA0008BE891E00197F1F761E086E00E94A116D0 +:101CB00083E592E00197F1F760E086E00C94A116CD +:101CC00060E086E00E94A11683E795E00197F1F7B6 +:101CD00061E086E00E94A11683E592E00197F1F7AA +:101CE00060E086E00C94A1160E94B534E6E5F5E0CC +:101CF00016821782108611861286138614826AE570 +:101D000075E0CF010C946E27CF92DF92FF920F9374 +:101D10001F93CF93DF936C01C62FF42E61E086E012 +:101D20000E94A1168BEB93E00197F1F760E086E04B +:101D30000E94A1160E94600E0E944C0E0E944C0E42 +:101D4000CC23F1F00FE110E0F60180819181A281B6 +:101D5000B381002E04C0B695A795979587950A94F0 +:101D6000D2F780FF03C00E94600E02C00E944C0E9A +:101D70000150110948F724E0C20ED11CC150E0CF38 +:101D8000C2E0D0E00F2D10E0C8010C2E02C09595E6 +:101D900087950A94E2F780FF03C00E94600E02C09C +:101DA0000E944C0E219780F7DF91CF911F910F91E8 +:101DB000FF90DF90CF900895FC018091490481113C +:101DC00003C08FEF9FEF08959FB7F89482E0809350 +:101DD000E9002091F20030E01216130614F421E01D +:101DE00030E02115310559F0289A84E680934804A3 +:101DF0008091F10080838091F200882319F09FBFC9 +:101E0000C90108958BE68093E800F9CFE82FF0E050 +:101E1000EE0FFF1FE45FFE4F718360838230D9F0C5 +:101E200028F4882341F0813071F008958330D9F08F +:101E3000843009F10895809169008C7F81608093DE +:101E40006900E89A089580916900837F8460809397 +:101E50006900E99A0895809169008F7C8061809380 +:101E60006900EA9A0895809169008F738064809375 +:101E70006900EB9A089580916A008F7C806180935D +:101E80006A00EE9A089580916A0590916B058F3FE4 +:101E90002FEF920791F01092620510926305109255 +:101EA0006405109265051092A7051092A60585306D +:101EB00020F46CEF75E20C94060F0895CF93DF9336 +:101EC0004115510559F4E0915004F09151040190ED +:101ED000F081E02D80E594E0099507C0242FAB0147 +:101EE000BC0180E594E00E943215EC016AE172E0E9 +:101EF00080E594E00E941D158C0F9D1FDF91CF910E +:101F000008958EBD0DB407FEFDCF8EB508950F93D5 +:101F10001F93CF93DF93082F162FC3E7D5E060E020 +:101F20008A810E94A116802F0E94810F812F0E941A +:101F3000810F61E08A81DF91CF911F910F910C9405 +:101F4000A1161F93CF93DF93182FC3E7D5E060E06E +:101F50008A810E94A116812F0E94810F61E08A81EF +:101F6000DF91CF911F910C94A1161F93CF93DF9314 +:101F700060E0809175050E94A1168EE70E94810F96 +:101F8000CBE3D1E01C2F185F89910E94810F1C13B5 +:101F9000FBCF61E080917505DF91CF911F910C948B +:101FA000A116CF93DF9390917C05981304C0909174 +:101FB0007D05961771F0C62FD82F682F84E00E94F8 +:101FC000870F6C2F85E00E94870FD0937C05C0930C +:101FD0007D05DF91CF910895CF93DF93C3E7D5E0DF +:101FE00061E08A810E94A1168FE090E00197F1F7ED +:101FF00060E08A810E94A11683E290E00197F1F7E8 +:1020000061E08A810E94A1168FE990E00197F1F7C3 +:1020100060E08A810E94A1166AE070E080E090E0B2 +:102020000E94321780E30E94810F6AE070E080E036 +:1020300090E00E94321761E08A81DF91CF910C9489 +:10204000A11661E080E10E94D11660E08EE00E945E +:10205000D11661E08FE00E94D11661E08FE00E940E +:10206000A11660E080E10E94A11680E58CBD089574 +:1020700061E0809175050E94D1160E94211060E0F8 +:1020800082E00E94D11664E070E080E090E00E945F +:1020900032170E94EC0F69E280E00E94870F6EE227 +:1020A00081E00E94870F66E082E00E94870F67E46C +:1020B00083E00E94870F6FEF86E00E94870F60E049 +:1020C00087E00E94870F60E388E00E94870F61E944 +:1020D00083ED0E94D10F80917E05882331F060E06E +:1020E00089E00E94870F10927E0580917B058823EE +:1020F00031F060E08AE00E94870F10927B0566E075 +:102100008BE00E94870F60E08CE00E94870F60E107 +:102110008DE00E94870F60EB8EE00E94870F61E7E1 +:102120008FE00E94870F82E080937A0568EF80E15C +:102130000E94870F63E981E10E94870F63E382E1D8 +:102140000E94870F62E283E10E94870F68EF84E1BB +:102150000E94870F60E085E10E94870F67E086E1BB +:102160000E94870F60E287E10E94870F68E188E1A3 +:102170000E94870F66E189E10E94870F6CE68AE181 +:102180000E94870F60E08BE10E94870F60E48CE182 +:102190000E94870F61E98DE10E94870F67E88EE159 +:1021A0000E94870F6BE68FE10E94870F6BEF80E242 +:1021B0000E94870F66E581E20E94870F61E182E25B +:1021C0000E94870F69EE83E20E94870F6AE284E231 +:1021D0000E94870F60E085E20E94870F6FE186E230 +:1021E0000E94870F61E487E20E94870F60E088E227 +:1021F0000E94870F69E589E20E94870F6FE78AE2F4 +:102200000E94870F6FE38BE20E94870F61E88CE2E8 +:102210000E94870F65E38DE20E94870F6BE08EE2DC +:102220000E94870F0C94B50F80917F0590918005D7 +:102230008F3F2FEF920791F010926605109267057D +:10224000109268051092690510924F0410924E0486 +:10225000853020F463E973E20C94060F0895CF9360 +:10226000DF932091920530919305232B79F0FC01A7 +:10227000C0918E05D0918F0560817181CE010E9441 +:10228000DE34009719F08C1B9D0B02C08FEF9FEF7F +:10229000DF91CF910895CF93DF93EBE1F1E084914B +:1022A000ECEFF0E0D491EDEDF0E0C491CC2391F0AF +:1022B00081110E946416EC2FF0E0EE0FFF1FE65331 +:1022C000FF4FA591B491EC91ED2381E090E021F4D2 +:1022D00080E002C080E090E0DF91CF9108950F93FD +:1022E0001F93CF93DF93BC016C5E7F4FFC01408155 +:1022F0005181DA0120E030E0109729F02A273B27AE +:10230000B695A795F9CF440F551F21703327240F99 +:10231000351F21933193E617F70749F7E4E0F0E022 +:10232000A1E0B0E08D010E2E02C0000F111F0A9433 +:10233000E2F7EC0120E030E049915991402351232C +:102340000E2E02C0559547950A94E2F724273527AB +:10235000C617D70789F73197217033270E2E02C091 +:10236000220F331F0A94E2F740914C0450914D0420 +:10237000240F351F30934D0420934C04309791F671 +:10238000220F331FFC01358B248B10924D041092C9 +:102390004C04DF91CF911F910F9108952F923F929E +:1023A0004F925F926F927F928F929F92AF92BF9265 +:1023B000CF92DF92EF92FF920F931F93CF93DF9311 +:1023C000CDB7DEB76B970FB6F894DEBF0FBECDBFAB +:1023D0009C01207F3327E4E035952795EA95E1F7C6 +:1023E0003A8329838F7099279C838B83FE013596CE +:1023F00020E030E0AFE0CA2ED12CE12CF12C890195 +:10240000045E1F4FD701C601002E04C0880F991F1C +:10241000AA1FBB1F0A94D2F784239523A623B723B0 +:1024200004C0B695A795979587950A95D2F781939D +:10243000919324503109203E8FEF380701F7CE01E8 +:1024400001960E946F11DC01E0E0F0E0D12CE12C5C +:10245000F12C212C312C412C20E8C22E8FEF8B8FB8 +:102460008C9111963C9111971296282F932F990FCA +:10247000990B8F010E5C1F4F492F592F692F792F10 +:10248000892F0E949F3359013A014B018C012D2D58 +:102490003E2D4F2D522D632D742D8C2D9B8D630160 +:1024A00074010E94D633522E132FB42EA52E962ED1 +:1024B000872E782E692ED22EE32EF42E252E362E40 +:1024C000472EC82E9B8F3597E93C8FEFF80741F6D2 +:1024D00080E4E82EF12C93EEC92E93E0D92E81E012 +:1024E000E81AF108252D312F4B2D5A2D692D782D05 +:1024F000872D962D0E2D0E94BA33217030E040E0DA +:1025000050E060E070E080E090E0A0E00E94DF3307 +:1025100041F086E00E94A116C6010197F1F761E043 +:1025200008C061E086E00E94A116C6010197F1F79C +:1025300060E086E00E94A116C6010197F1F7E11460 +:10254000F10469F66B960FB6F894DEBF0FBECDBFEF +:10255000DF91CF911F910F91FF90EF90DF90CF907F +:10256000BF90AF909F908F907F906F905F904F90B3 +:102570003F902F9008951F93CF93DF93182FC3E7B9 +:10258000D5E060E08A810E94A116812F806C0E94B4 +:10259000810F80E00E94810F182F61E08A810E94E4 +:1025A000A116812FDF91CF911F9108957F928F9275 +:1025B0009F92AF92BF92CF92DF92EF92FF920F93D2 +:1025C0001F93CF93DF93CDB7DEB7762E6A018DB61A +:1025D0009EB62DB73EB7241B350B0FB6F8943EBF01 +:1025E0000FBE2DBFEDB7FEB731967F01BC018DEE5A +:1025F00094E00E94F6156BE073E08DEE94E00E948B +:10260000F615570100E010E0872D800F0C151D0511 +:10261000B9F00E94BB12F50181935F01482F50E091 +:1026200060E070E020E18DEE94E00E9432156EE0F3 +:1026300073E08DEE94E00E94F6150F5F1F4FE4CF1C +:102640006CE172E08DEE94E00E94E215C7010FB6D6 +:10265000F8949EBE0FBE8DBEDF91CF911F910F915A +:10266000FF90EF90DF90CF90BF90AF909F908F90B2 +:102670007F9008952FB7F89487708093E900909128 +:10268000E800892F807295FF04C09091F20080E4E9 +:10269000891B2FBF0895CF92DF92EF92FF920F9385 +:1026A0001F93CF93DF936C017A018B01C0E0D0E0E0 +:1026B000CE15DF0589F0D8016D918D01D601ED9120 +:1026C000FC910190F081E02DC6010995892B11F450 +:1026D0007E0102C02196ECCFC701DF91CF911F91FF +:1026E0000F91FF90EF90DF90CF900895FC01538DF4 +:1026F000448D252F30E0842F90E0821B930B5417DC +:1027000010F0CF96089501970895FC01918D828D68 +:10271000981761F0828DDF01A80FB11D5D968C9135 +:10272000928D9F5F9F73928F90E008958FEF9FEF40 +:102730000895FC01918D828D981731F0828DE80FFC +:10274000F11D858D90E008958FEF9FEF0895FC01B6 +:10275000918D228D892F90E0805C9F4F821B910983 +:102760008F739927089580E594E00E94A71321E0D4 +:10277000892B09F420E0822F0895FC01848DDF016C +:10278000A80FB11DA35ABF4F2C91848D90E00196E4 +:102790008F739927848FA689B7892C93A089B189D3 +:1027A0008C9180648C93938D848D981306C00288DD +:1027B000F389E02D80818F7D80830895EF92FF92D1 +:1027C0000F931F93CF93DF93EC0181E0888F9B8D54 +:1027D0008C8D981305C0E889F989808185FD24C016 +:1027E000F62E0B8D10E00F5F1F4F0F731127E02E99 +:1027F0008C8DE8120CC00FB607FCFACFE889F98976 +:10280000808185FFF5CFCE010E94BD13F1CF8B8D66 +:10281000FE01E80FF11DE35AFF4FF0820B8FEA89AA +:10282000FB898081806207C0EE89FF896083E88927 +:10283000F98980818064808381E090E0DF91CF918D +:102840001F910F91FF90EF900895CF93DF93EC01CC +:10285000888D8823C9F0EA89FB89808185FD05C0C0 +:10286000A889B9898C9186FD0FC00FB607FCF5CFFA +:10287000808185FFF2CFA889B9898C9185FFEDCF42 +:10288000CE010E94BD13E7CFDF91CF91089580E084 +:1028900090E0892B29F00E94B31381110C94000061 +:1028A0000895CF93DF931F92CDB7DEB76983DC0124 +:1028B000ED91FC910280F381E02D41E050E0BE01FA +:1028C0006F5F7F4F09950F90DF91CF91089583E05F +:1028D0008093E9008091F200882319F08AE38093C5 +:1028E000E800089583E00E943A1390E00895FC0107 +:1028F0008485958597FD0BC09FB7F89482E08093FF +:10290000E9008091F2009FBF90E0019608959FB783 +:10291000F89482E08093E9008091F2009FBF90E0FC +:10292000089508950F931F93CF93DF931F92CDB710 +:10293000DEB78C01FC018485958597FF0EC0CE0122 +:1029400001960E94DC0E019719F4298130E002C043 +:102950002FEF3FEFF80135872487F80184859585AF +:102960000F90DF91CF911F910F910895CF93DF9337 +:102970001F92CDB7DEB7FC018485958597FD05C014 +:102980002FEF3FEF358724870BC0CE0101960E94C1 +:10299000DC0E019719F4898190E002C08FEF9FEF60 +:1029A0000F90DF91CF9108954091EB055091EC0588 +:1029B0002091E9053091EA0542175307B4F490914C +:1029C000E8009570E1F39091E80092FD19C08093C2 +:1029D000F1008091EB059091EC0501968F7399279A +:1029E000892B19F48EEF8093E8008091EB0590918C +:1029F000EC0501969093EC058093EB0581E008953A +:102A000080E00895615030F02091F100FC012083B6 +:102A10000196F8CF289A84E6809348040895DC0153 +:102A2000ED91FC91DB0114964D915C9115976D91A0 +:102A30007C910280F381E02D09946115710579F094 +:102A4000FB0101900020E9F73197AF01461B570BBE +:102A5000DC01ED91FC910280F381E02D099480E08E +:102A600090E008954F925F926F927F92EF92FF9263 +:102A70000F931F93CF93DF93CDB7DEB7A1970FB618 +:102A8000F894DEBF0FBECDBF7C01FA01CB0119A2C5 +:102A9000223008F42AE08E010F5D1F4F422E512C88 +:102AA000612C712CBF01A30192010E945232F901E5 +:102AB000CA01015011096A3014F4605D01C0695CFB +:102AC000D8016C93232B242B252B61F7B801C70168 +:102AD0000E941D15A1960FB6F894DEBF0FBECDBFA4 +:102AE000DF91CF911F910F91FF90EF907F906F90AA +:102AF0005F904F900895CF92DF92EF92FF920F93E5 +:102B00001F93CF93DF93EC016A017B0121153105FF +:102B100079F4E881F9810190F081E02D642FDF9153 +:102B2000CF911F910F91FF90EF90DF90CF9009947C +:102B30002A30310509F577FF1EC0E881F98101903F +:102B4000F081E02D6DE209958C0144275527BA01EB +:102B50004C195D096E097F092AE0CE010E943215E9 +:102B6000800F911FDF91CF911F910F91FF90EF90F8 +:102B7000DF90CF9008952AE0B701A601CE01DF9142 +:102B8000CF911F910F91FF90EF90DF90CF900C9419 +:102B900032150F931F93CF93DF93EC019A01AB0192 +:102BA000770F660B770B0E947B158C016AE172E050 +:102BB000CE010E941D15800F911FDF91CF911F91B3 +:102BC0000F9108950F931F93CF93DF93EC010E9411 +:102BD0001D158C016AE172E0CE010E941D15800F67 +:102BE000911FDF91CF911F910F9108950C941D15A6 +:102BF0008091E10581110DC082E08093DD0584E0C4 +:102C00008093DE051092E0051092DF0581E080934D +:102C1000E1058DED95E008951F920F920FB60F928A +:102C200011242F933F934F935F936F937F938F93D1 +:102C30009F93AF93BF93EF93FF9380E594E00E943F +:102C4000BD13FF91EF91BF91AF919F918F917F91B4 +:102C50006F915F914F913F912F910F900FBE0F9009 +:102C60001F9018951F920F920FB60F9211242F9359 +:102C70008F939F93EF93FF93E0916004F091610431 +:102C80008081E0916604F091670482FD12C090811A +:102C9000809169048F5F8F7320916A04821751F0CD +:102CA000E0916904F0E0E05BFB4F958F809369044D +:102CB00001C08081FF91EF919F918F912F910F9093 +:102CC0000FBE0F901F90189590E0FC013197EF30E8 +:102CD000F105B0F5EA5AFF4F0C94993380918000CA +:102CE0008F7703C0809180008F7D8093800008954E +:102CF00080918000877FF9CF84B58F7702C084B53B +:102D00008F7D84BD0895809190008F7707C080915A +:102D100090008F7D03C080919000877F809390000A +:102D200008958091C0008F7703C08091C0008F7D8F +:102D30008093C00008958091C200877F8093C20075 +:102D400008951F93CF93DF93282F30E0F901EA5EB7 +:102D5000FE4F8491F901E950FF4FD491F901E852F7 +:102D6000FF4FC491CC23C9F0162F81110E94641625 +:102D7000EC2FF0E0EE0FFF1FEF54FE4FA591B49142 +:102D80008FB7F894111105C09C91ED2FE095E923C0 +:102D900002C0EC91ED2BEC938FBFDF91CF911F918F +:102DA0000895CF93DF9390E0FC01E950FF4F249109 +:102DB000FC01E852FF4F8491882361F190E0880F75 +:102DC000991FFC01ED55FE4FC591D491FC01EF54C4 +:102DD000FE4FA591B491611109C09FB7F894888105 +:102DE000209582238883EC912E230BC0623061F4FE +:102DF0009FB7F8943881822F809583238883EC9144 +:102E00002E2B2C939FBF06C08FB7F894E8812E2BF2 +:102E100028838FBFDF91CF9108953FB7F8948091B9 +:102E2000D9059091DA05A091DB05B091DC0526B5B6 +:102E3000A89B05C02F3F19F00196A11DB11D3FBFF2 +:102E4000BA2FA92F982F8827820F911DA11DB11D80 +:102E5000BC01CD0142E0660F771F881F991F4A957C +:102E6000D1F708958F929F92AF92BF92CF92DF9247 +:102E7000EF92FF926B017C010E940D174B015C01E8 +:102E8000C114D104E104F104F1F00E940D17DC013A +:102E9000CB0188199909AA09BB09883E9340A1056D +:102EA000B10570F321E0C21AD108E108F10888EEFB +:102EB000880E83E0981EA11CB11CC114D104E1044A +:102EC000F10419F7DDCFFF90EF90DF90CF90BF9026 +:102ED000AF909F908F9008957F928F929F92AF9224 +:102EE000BF92CF92DF92EF92FF920F931F93CF93F7 +:102EF000DF93C82E8B017A0180914904811103C0B0 +:102F00008FEF9FEF75C08091300480FF05C08091E6 +:102F1000E00082608093E000CE2DDF2DD12C8AEF7F +:102F2000882E8C2D8770B82E8C2D8072A82E8C2D1B +:102F30008074982E9AE3792E209709F452C08C2D34 +:102F40000E943A13282F81110AC08A948820C1F266 +:102F500061E070E080E090E00E943217EDCF90E0F9 +:102F6000C817D9070CF42C2F3FB7F894B092E9009A +:102F70008091E80085FF33C0822F90E0C81BD90BF9 +:102F8000AA2029F02150A8F01092F100FBCFF801FF +:102F9000C7FE07C0215058F044914093F10031968C +:102FA000F9CF215020F041914093F100FACF080F62 +:102FB000191FDD2019F07092E8000AC08091E80026 +:102FC00085FD08C07092E800DD24D394209739F085 +:102FD000D12C05C0209719F491107092E8003FBFE2 +:102FE000ABCFD110ACCF5D9A84E68093ED05C701DD +:102FF000DF91CF911F910F91FF90EF90DF90CF90D5 +:10300000BF90AF909F908F907F900895CF93DF9364 +:10301000EC0180912C01882331F083E00E946C1731 +:103020001816190634F081E090E09B838A8380E0D3 +:1030300090E0DF91CF9108952FB7F8946091D50576 +:103040007091D6058091D7059091D8052FBF08952E +:103050001F920F920FB60F9211242F933F938F93CD +:103060009F93AF93BF938091D5059091D605A09182 +:10307000D705B091D8053091D40523E0230F2D3723 +:1030800020F40196A11DB11D05C026E8230F02966C +:10309000A11DB11D2093D4058093D5059093D6052D +:1030A000A093D705B093D8058091D9059091DA0502 +:1030B000A091DB05B091DC050196A11DB11D8093A7 +:1030C000D9059093DA05A093DB05B093DC05BF9199 +:1030D000AF919F918F913F912F910F900FBE0F90C5 +:1030E0001F9018951F920F920FB60F9211242F93D5 +:1030F0003F934F935F936F937F938F939F93AF9380 +:10310000BF93EF93FF93E0911401F091150109959E +:10311000FF91EF91BF91AF919F918F917F916F91AF +:103120005F914F913F912F910F900FBE0F901F9085 +:1031300018951F920F920FB60F9211242F933F9361 +:103140004F935F936F937F938F939F93AF93BF93AF +:10315000EF93FF93E0911201F09113010995FF9114 +:10316000EF91BF91AF919F918F917F916F915F91FF +:103170004F913F912F910F900FBE0F901F90189578 +:103180001F920F920FB60F9211242F933F934F93DC +:103190005F936F937F938F939F93AF93BF93EF93BF +:1031A000FF93E0911001F09111010995FF91EF91CA +:1031B000BF91AF919F918F917F916F915F914F914F +:1031C0003F912F910F900FBE0F901F9018951F9257 +:1031D0000F920FB60F9211242F933F934F935F934B +:1031E0006F937F938F939F93AF93BF93EF93FF93CF +:1031F000E0910E01F0910F010995FF91EF91BF91C0 +:10320000AF919F918F917F916F915F914F913F917E +:103210002F910F900FBE0F901F9018951F920F9235 +:103220000FB60F9211242F933F934F935F936F9399 +:103230007F938F939F93AF93BF93EF93FF93E0910F +:103240000C01F0910D010995FF91EF91BF91AF91A4 +:103250009F918F917F916F915F914F913F912F91AE +:103260000F900FBE0F901F901895CF93DF93EC0136 +:1032700081E08C838D839E01265F3F4F3F832E83A9 +:103280001986188627E731E0398328831C861B8638 +:103290001E861D868F87888B81EC8A870E94F81591 +:1032A000FC0121818C8190E0820F911D089774F5BB +:1032B000A281B381109719F4D383C2830CC01896EE +:1032C0008D919C911997009711F0DC01F8CF199618 +:1032D000DC93CE93189780818A8381818B83908140 +:1032E0008D81890F808380E09C81891778F4AE817D +:1032F000BF81A80FB11D9C91A181B0E0A65EBE4F19 +:103300009C9391819F5F91838F5FEECFDF91CF91EF +:1033100008950895CF93DF93EC01888199810097F8 +:1033200011F00E949C30198218821D821C821B821F +:103330001A82DF91CF9108950F931F93CF93DF935C +:10334000EC0188819981009729F02A813B81261719 +:10335000370788F48B016F5F7F4F0E94EB33009734 +:1033600061F0998388831B830A832C813D81232B01 +:1033700011F4FC01108281E001C080E0DF91CF9167 +:103380001F910F910895EF92FF920F931F93CF9388 +:10339000DF93EC017B018A01BA010E949C19811123 +:1033A00004C0CE010E948A1907C01D830C83B70197 +:1033B000888199810E94D734CE01DF91CF911F91EE +:1033C0000F91FF90EF900895CF92DF92EF92FF92CE +:1033D0000F931F93CF93DF931F92CDB7DEB7182FB4 +:1033E000062FE42E862F880F8E5F99830E94D414B7 +:1033F00083E00E94D414F12EC12E9981D92E8C2DF8 +:103400008F19801798F4F601E7FE02C0849101C07D +:1034100080810E94D414182F80E00E94D41481234C +:10342000FFEFCF1ADF0A8111EACF01C081E00F90D0 +:10343000DF91CF911F910F91FF90EF90DF90CF9090 +:103440000895FC01248135816217730720F480817F +:103450009181009729F41092EE058EEE95E0089583 +:10346000860F971F0895FC0124813581232B31F4A9 +:1034700021E061157105A1F0FB0108C0FC0180810C +:1034800091816115710531F421E0FC01808188236F +:1034900039F005C00E94CE3421E0892B09F020E0EC +:1034A000822F0895EF92FF920F931F93CF93DF9394 +:1034B000FC01248135816115710511F480E019C08A +:1034C00041155105A9F07B01EC018A01020F131F80 +:1034D000B8010E949C19882389F3288139818C8145 +:1034E0009D81B701820F931F0E94D7341D830C83E7 +:1034F00081E0DF91CF911F910F91FF90EF900895A0 +:10350000CF93DF93EC016115710561F0FB01019030 +:103510000020E9F73197AF01461B570B0E94521A62 +:10352000811103C0CE010E948A19CE01DF91CF9193 +:103530000895CF93DF93EC01FB01448155816081B5 +:1035400071810E94521A811103C0CE010E948A1912 +:10355000CE01DF91CF9108956115710551F0FB0106 +:1035600001900020E9F73197AF01461B570B0C94EF +:10357000521A80E00895CF93DF93EC016115710535 +:1035800059F0FB0101900020E9F73197AF01461B8C +:10359000570B0E94C31902C00E948A19CE01DF9105 +:1035A000CF9108950F931F93CF93DF938C01EB017D +:1035B000FC01808191810097B1F06881798161156A +:1035C000710579F0428153812C813D814217530767 +:1035D00040F00E94D7348C819D81F80195838483CB +:1035E00013C00E949C3088819981F8019183808367 +:1035F0008A819B81938382838C819D81958384833F +:10360000198218821B821A821D821C82DF91CF913F +:103610001F910F910895FC01808191810C949C3041 +:10362000CF93DF9300D0CDB7DEB7FC0111821082BB +:10363000138212821582148269831A82BE016F5F1F +:103640007F4F0E94BB1A0F900F90DF91CF9108958A +:10365000FB01DC0111961C921E9213961C921E9285 +:10366000129715961C921E9214978617970749F089 +:10367000608171816115710521F0448155810C943F +:10368000C3190895FC0111821082138212821582DF +:1036900014826115710551F0FB0101900020E9F7DA +:1036A0003197AF01461B570B0C94C3190895BF9275 +:1036B000CF92DF92EF92FF920F931F93CF93DF93FE +:1036C0007C016B018A01E9012417350720F4812F61 +:1036D0008901C42FD82F6CE172E0C7010E94421B00 +:1036E000D60114968D919C91159708171907D0F45F +:1036F0008C179D0708F4EC01D601ED91FC91119710 +:10370000EC0FFD1FB08010824D915C91BA01600FEB +:10371000711FC7010E94BB1AD601ED91FC91EC0FFD +:10372000FD1FB082C701DF91CF911F910F91FF90D4 +:10373000EF90DF90CF90BF9008951F920F920FB639 +:103740000F9211248F939F938091E1009091E1005B +:10375000937F9093E10083FF0FC01092E90091E006 +:103760009093EB001092EC0092E39093ED00109296 +:10377000490498E09093F00082FF20C093E090937A +:10378000E9009091F200992319F09AE39093E800F0 +:103790009091ED05992339F09091ED05915090931A +:1037A000ED05992389F190914804992339F090917E +:1037B0004804915090934804992341F184FF10C02C +:1037C0008091E2008E7E81608093E2008091E10032 +:1037D0008F7E8093E100809130048E7E806111C0E5 +:1037E00080FF16C08091E2008E7E80618093E200AF +:1037F0008091E1008E7E8093E100809130048E7E86 +:1038000081608093300404C05D98CDCF2898D6CFD6 +:103810009F918F910F900FBE0F901F901895DF9280 +:10382000EF92FF920F931F93CF93DF93D82E8A01CD +:103830007B01E40EF51EEB01CE15DF0571F0D7FE1E +:1038400003C0FE01849101C088810E94D414219696 +:103850008111F2CF8FEF9FEF01C0C801DF91CF91AF +:103860001F910F91FF90EF90DF9008950F931F939A +:10387000CF93DF931F92CDB7DEB782E0898342E416 +:1038800050E06FEB71E080E80E940F1C0E94F81579 +:10389000DC0112960D911C9113970115110569F029 +:1038A000D801ED91FC910280F381E02DBE016F5FA4 +:1038B0007F4FC801099597FF07C089810F90DF915D +:1038C000CF911F910F910895F80100851185E5CFE3 +:1038D0001F920F920FB60F921124CF92DF92EF92A8 +:1038E000FF920F931F932F933F934F935F936F9389 +:1038F0007F938F939F93AF93BF93EF93FF93CF9358 +:10390000DF93CDB7DEB76C97DEBFCDBF1092E90075 +:103910008091E80083FFEDC168E0CE0145960E94EA +:10392000021582EF8093E8008D8987FF05C0909192 +:10393000E80090FFFCCF03C09EEF9093E800982F23 +:10394000907609F0C6C09E892F89188D91110CC000 +:10395000803829F4809131048093F10002C01092E4 +:10396000F1001092F10048C1422F50E0512B9130EC +:1039700051F4811141C14130510509F03DC180919F +:1039800031048D7F0BC0933061F4811135C141301A +:10399000510509F031C18091310482608093310476 +:1039A0002BC1953041F48091E80080FFFCCF206866 +:1039B0002093E30021C1963009F05FC0EB8CFC8CB2 +:1039C0001092E9001092EC051092EB05123091F57F +:1039D0001092EA051092E9050E94361C99E0BE019A +:1039E0006F5F7F4FDB01E92F1D92EA95E9F799831D +:1039F0001A8391E09E8390EA98879AEF99872091A5 +:103A0000EB053091EC05275F3F4F3C832B838D8383 +:103A10001092E9001092EC051092EB05F092EA0585 +:103A2000E092E90549E050E080E00E940F1C0E940E +:103A3000361CE2C0F092EA05E092E9050E94F81512 +:103A4000DC011296ED90FC901397E114F10409F457 +:103A5000C0C0D701ED91FC910480F581E02DBE013D +:103A60006B5E7F4FC7010995009719F00CF0C4C039 +:103A7000C7C0F701E084F184E8CF973009F4C0C0F3 +:103A8000983021F481E08093F100B6C0993009F0BC +:103A9000B3C0837009F0B4C0EBE1F1E081E021E054 +:103AA00036E39081992361F08093E9002093EB0045 +:103AB00091919093EC003093ED008F5F873089F700 +:103AC0008EE78093EA001092EA008F898093490480 +:103AD00093C08B8D9C8D1092E9001092EC05109292 +:103AE000EB059093EA058093E905898D811156C015 +:103AF0008E899D89913A59F4813209F081C047E05D +:103B000050E065E271E080E00E940F1C75C09132C8 +:103B100009F076C0833289F4888D90E0982F882749 +:103B20002F89822BA0E0B0E08093210190932201A5 +:103B3000A0932301B09324015FC0803269F4809187 +:103B4000E80082FFFCCF67E085E291E00E94021569 +:103B50008BEF8093E80006C0823209F04DC08F8958 +:103B600080932C0180912F04882319F0EEEFFAE066 +:103B700002C0E0E0F8E08091250190912601A0913B +:103B80002701B0912801803B9440A105B10509F0BF +:103B90007BC080912C0180FF93C076C00E94F815F5 +:103BA000DC0112960D911C9113970115110541F13D +:103BB000D801ED91FC910190F081E02DBE016B5E8A +:103BC0007F4FC8010995811117C0F8010085118543 +:103BD000ECCF113009F44EC0133091F48F89882353 +:103BE00009F445C0823081F440E86DE083E292E060 +:103BF0000E94E419882321F08EEF8093E80079C0B9 +:103C000081E28093EB0075C0813029F440E86BE0DD +:103C100087E192E0EDCF833099F70E94F815DC013F +:103C20001296ED90FC9013978E010F5F1F4F680165 +:103C3000E114F10479F0D701ED91FC910680F78150 +:103C4000E02DB801C7010995080F111DF701E084A7 +:103C5000F184EECFD8011C92F60101900020E9F723 +:103C60003197BF016C197D0940E0C601C1CF61E009 +:103C700072E002C065E072E06115710509F2FB01B6 +:103C8000449150E080E840CF0FB6F894A895809119 +:103C90006000886180936000109260000FBEA8955C +:103CA000EE3F2AE0F20739F08091FE0A9091FF0A78 +:103CB00091838083A1CF1092FF0A1092FE0A9CCFBD +:103CC000EE3F8AE0F80731F0808191819093FF0AFE +:103CD0008093FE0A87E797E7918380839BE088E1E2 +:103CE0000FB6F894A895809360000FBE9093600083 +:103CF00083CF6C960FB6F894DEBF0FBECDBFDF91B9 +:103D0000CF91FF91EF91BF91AF919F918F917F9153 +:103D10006F915F914F913F912F911F910F91FF9064 +:103D2000EF90DF90CF900F900FBE0F901F901895DF +:103D300061E084E10E94A1168FEB94E00197F1F716 +:103D400060E084E10E94A11687E49EE00197F1F70C +:103D500060E084E10C94A11661E084E10E94A11668 +:103D600087E49EE00197F1F760E084E10E94A116EC +:103D70008FEB94E00197F1F760E084E10C94A116D9 +:103D800060E084E10E94A11687EB91E00197F1F7D2 +:103D9000089561E084E10E94A11687EB91E001970C +:103DA000F1F708957F928F929F92AF92BF92CF9238 +:103DB000DF92EF92FF920F931F93CF93DF93EC016B +:103DC00081E090E09093F0058093EF057E01BE01C5 +:103DD000685F7F4FFE012FEF3FEFE617F70799F07F +:103DE0008191382788E090E0A901440F551F37FFE3 +:103DF00006C09A01A1E22A27A0E13A2701C09A0150 +:103E0000019791F7EACF288739870E94C01E0E9448 +:103E1000C91E0E94C01E0E94C91E0E94C01E0E9490 +:103E2000C91E0E94C01E0E94C91E0E94C01E0E9480 +:103E3000C91E0E94C01E0E94C91E0E94C01E0E9470 +:103E4000C01E0E94C91E0E94C91E0E94C91E0E9457 +:103E5000C91E0E94C91E0E94C91E0E94C91E0E943E +:103E6000C91E0E94C91E2A9607EB11E093E7A92EEE +:103E700093E0B92E88248394912CF70171907F01EF +:103E800088E0C82ED12C8091EF059091F00577FE47 +:103E90000EC0892B31F060E084E10E94A116C501BB +:103EA00027C061E084E10E94A116C5010EC0892BE4 +:103EB00099F060E084E10E94A116C8010197F1F732 +:103EC00061E084E10E94A116C8010197F1F7909288 +:103ED000F0058092EF0512C061E084E10E94A11616 +:103EE000C8010197F1F760E084E10E94A116C801C2 +:103EF0000197F1F71092F0051092EF05770CF1E0C1 +:103F0000CF1AD10809F0BFCFEC16FD0609F0B5CFE6 +:103F100061E084E10E94A1168FE295E00197F1F73C +:103F200060E084E1DF91CF911F910F91FF90EF90BE +:103F3000DF90CF90BF90AF909F908F907F900C9428 +:103F4000A116AF92BF92CF92DF92EF92FF920F93A2 +:103F50001F93CF93DF9300D000D0CDB7DEB78A0197 +:103F600024E1A22EB12C21E0A21AB1086B017C0140 +:103F70000A2C04C0F694E794D794C7940A94D2F715 +:103F800069837A838B839C83C0FE07C00E94AC1E2A +:103F900069817A818B819C8106C00E94981E9C81D8 +:103FA0008B817A816981A114B104E9F684E0E82E5D +:103FB000F12C81E0E81AF108C8010E2C02C0959599 +:103FC00087950A94E2F780FF03C00E94AC1E02C0EE +:103FD0000E94981EE114F10461F70F900F900F906A +:103FE0000F90DF91CF911F910F91FF90EF90DF9095 +:103FF000CF90BF90AF900C94981E0F931F93CF93C8 +:10400000DF938C0185E30E94A10FC3E8DCE0CE01C1 +:104010000197F1F7C8010E94D21E86E30E94A10F0A +:1040200061E470E080E090E00E94321785E30E9436 +:10403000A10F2197F1F7C8010E94D21E86E30E94CA +:10404000A10F61E470E080E090E0DF91CF911F91DB +:104050000F910C943217CF92DF92EF92FF920E9451 +:10406000473126E03EE546EC53E40E94E4320E94EC +:1040700056336B017C01B701882799278DE00E9498 +:10408000870F99278F2D7E2D6D2D8EE00E94870F33 +:104090006C2D8FE0FF90EF90DF90CF900C94870F06 +:1040A00085E190E090937605809375050E94381025 +:1040B0006FEF8FEF0E94D10F60E977E78EED99E106 +:1040C0000E942B2064E087E00E94870F85E30E9416 +:1040D000A10F6DE080E00C94870F85E190E0909354 +:1040E0007605809375050E9438106FEF8FEF0E9460 +:1040F000D10F6091060170910701809108019091A4 +:1041000009010E942B2064E087E00E94870F85E36D +:104110000E94A10F6DE080E00C94870F85E190E094 +:1041200090937605809375050E9438106091060182 +:104130007091070180910801909109010E942B2044 +:1041400064E087E00E94870F6DE080E00E94870FA7 +:1041500067E080E10E94870F63E981E10E94870F99 +:1041600084E30C94A10F4F925F926F927F928F9293 +:104170009F92AF92BF92CF92DF92EF92FF920F93F6 +:104180001F93CF93DF93CDB7DEB7E9970FB6F894BF +:10419000DEBF0FBECDBF85E190E0909376058093A2 +:1041A00075050E94381086E30E94A10F60910201FC +:1041B0007091030180910401909105010E942B20D0 +:1041C00085E30E94A10F61E084E10E94A11687EBC4 +:1041D0009FEF9093F2058093F105EE24E394F12C88 +:1041E0008091240490912504009709F4AFC1813097 +:1041F000910541F0029709F08AC161E084E10E94D3 +:10420000A11685C1C114D10449F080912A0490916E +:104210002B04A0912C04B0912D0408C08091260499 +:1042200090912704A0912804B09129048093020161 +:1042300090930301A0930401B093050181E0C82687 +:1042400081E0C822DD2486E30E94A10F6091020173 +:104250007091030180910401909105010E942B202F +:1042600084E30E94A10F62E070E080E090E00E9491 +:10427000321760E0809175050E94A11684EF0E94BC +:10428000810F80E00E94810F082F61E08091750509 +:104290000E94A11610E0013811052CF01A9517FFA5 +:1042A00002C00F5F1F4F159507950B5411098091A0 +:1042B000F1059091F205801791070CF0BFC086E3DD +:1042C0000E94A10F6091020170910301809104018D +:1042D000909105010E942B2085E30E94A10F61E0CF +:1042E00084E10E94A11665E070E080E090E00E9409 +:1042F000321760E084E10E94A1160E941C184B0155 +:104300005C010E941C184090440450904504609049 +:10431000460470904704DC01CB0184199509A60975 +:10432000B70986399105A105B10508F48AC06091E5 +:1043300002017091030180910401909105011FA673 +:104340001EA619AA18AA1BAA1AAA2AE0AE014F5F34 +:104350005F4F0E94CB2FBE016F5F7F4FCE018E96C5 +:104360000E94BB1A23E030E040E050E0BE01625DF5 +:104370007F4FCE01C4960E94571B19A618A61BA6F4 +:104380001AA61DA61CA64AE0BE016F5F7F4FC8019A +:104390000E94A92FBE016F5F7F4FCE0188960E94B9 +:1043A000BB1A60EF73E0CE0182960E94421BBE01F1 +:1043B000685D7F4FCE0182960E94991A6FEF73E07D +:1043C0000E94801ABE016C5C7F4F0E94991A68E0BF +:1043D00074E00E94801ABC01CE0101960E94281B45 +:1043E000CE0182960E940B1BCE0188960E940B1B69 +:1043F000CE01C4960E940B1BCE018E960E940B1B11 +:10440000BE016F5F7F4F80E594E00E940F156AE167 +:1044100072E080E594E00E941D150E941C184B017B +:104420005C01609344047093450480934604909328 +:104430004704CE0101960E940B1B03C0FF2009F424 +:1044400066C00E941C18DC01CB0188199909AA09D1 +:10445000BB09893C9105A105B10508F06DC0EE20AE +:1044600009F453C060EF73E080E594E00E94F61514 +:10447000A801110F660B770B2AE030E080E594E08D +:104480000E947B156FEF73E080E594E00E94F615C3 +:1044900060910201709103018091040190910501E6 +:1044A0001BA21AA21DA21CA21FA21EA22AE0AE01DC +:1044B0004F5F5F4F0E94CB2FBE016F5F7F4FCE01DA +:1044C00082960E94BB1A23E030E040E050E0BE013B +:1044D0006E5D7F4FCE0101960E94571BBE016F5F3C +:1044E0007F4F80E594E00E940F15CE0101960E9457 +:1044F0000B1BCE0182960E940B1B68E074E080E5E6 +:1045000094E00E94E215E12C1FC0FF24F39480E5A3 +:1045100094E00E94A713181619060CF061CE1092B1 +:104520002504109224040E948E2063E773E080E546 +:1045300094E00E94E21554CE6CE074E080E594E0D3 +:104540000E94E215EE24E394F12CE1CFE9960FB638 +:10455000F894DEBF0FBECDBFDF91CF911F910F91B9 +:10456000FF90EF90DF90CF90BF90AF909F908F9093 +:104570007F906F905F904F900895DC01FB01129641 +:104580008C91129790E02481358182179307D1F4A2 +:1045900091818081813A31F481E0913091F09330C2 +:1045A00089F411C0813271F49B3021F482811F960D +:1045B0008C9305C09A3031F4828150968C9381E0BF +:1045C0000895089580E00895DC01FB0188E480836C +:1045D00089E4818384E482831D969C911D979F705A +:1045E0009F5B93831D968D919C911E9724E09695D9 +:1045F00087952A95E1F78F708F5B848385E0089516 +:10460000FC0182818F5BFB01808381E00895089526 +:1046100080E090E00895EF92FF920F931F93CF9365 +:10462000DF93FB012081213851F52381223239F5B6 +:10463000DC0112962C9130E04481558142175307DA +:10464000F1F4EC010B851C85E12CF12C0115110511 +:1046500091F0F801448155816281738180E80E9464 +:104660000F1C8F3FFFEF9F0769F0E80EF91ED8017E +:104670000D911C91EBCF81E08F87C70105C080E0D1 +:1046800090E002C08FEF9FEFDF91CF911F910F91CC +:10469000FF90EF900895CF93DF93CDB7DEB7699782 +:1046A0000FB6F894DEBF0FBECDBFFC01DB018C91CD +:1046B0008F5F8C93BE016F5F7F4F89E1DB011D929D +:1046C0008A95E9F729E0298384E08A8391E09D8334 +:1046D00083E08E832A8721E22B879C879D879F8793 +:1046E00022E2288B27E02B8B25E02C8B8E8B20E47D +:1046F00030E0388F2F8B998F82818B8395858685CB +:10470000998B8A8B838180688D8B49E150E080E0B2 +:104710000E940F1C69960FB6F894DEBF0FBECDBF86 +:10472000DF91CF9108952F923F924F925F926F92B7 +:104730007F928F929F92AF92BF92CF92DF92EF9231 +:10474000FF920F931F93CF93DF93CDB7DEB765979B +:104750000FB6F894DEBF0FBECDBF0E940D176B01E0 +:104760007C0180911B0890911C082601481A590A67 +:104770002DEC421620E1520608F4F6C08091950710 +:1047800090919607A201481B590BCA0157FF03C01D +:10479000919581959109883C91050CF0E1C080913B +:1047A00093079091940701969093940780939307B1 +:1047B000029709F0D5C094E6692E91E0792E01E0C8 +:1047C00010E020909107309092073B862A8649E0BE +:1047D00050E0B301CE0101960E94A02F8C816B8125 +:1047E000681708F4682F70E08091950790919607FC +:1047F0000E9485339B014091180150911901649FDB +:10480000C001659F900D749F900D112464E670E0C7 +:104810000E9485338985811103C0A1E0B0E002C008 +:10482000A2E0B0E08D81829FA001839F500D1124F2 +:104830005D874C878E81829F1001839F300C1124ED +:104840003F862E868F81829FA001839F500D112469 +:10485000598B488B8885829F1001839F300C1124CF +:104860003B8A2A8AFD01EE0FFF1FEB56F84F812C81 +:10487000912C54014A855B85415051095D8B4C8BCD +:104880008C899D89A817B90708F040C0880C991C2D +:10489000AA1CBB1C80819181AC012C843D844219EF +:1048A000530957FF03C051954195510946175707C2 +:1048B00070F4428153812E843F844219530957FF7B +:1048C00003C051954195510946175707E0F02888D4 +:1048D00039888219930997FF03C0919581959109B1 +:1048E0008617970780F5828193814A895B89841BAB +:1048F000950B97FF03C091958195910986179707AE +:1049000010F5689480F812963496BACF4A855B8584 +:1049100048305105C0F08092660590926705A092DC +:104920006805B09269051C013694279430924F04B3 +:1049300020924E043093900720938F0710934304E6 +:104940000093420409C00F5F1F4F59E0650E711CB0 +:104950000830110509F035CF109294071092930793 +:10496000109292071092910780919107909192076F +:104970008334910540F010929207109291071092A3 +:1049800094071092930780919107909192079C0150 +:104990002F5F3F4F3093920720939107880F991F05 +:1049A000FC01EB56F84F51824082C0921B08D09216 +:1049B0001C08E0921D08F0921E0865960FB6F89448 +:1049C000DEBF0FBECDBFDF91CF911F910F91FF9042 +:1049D000EF90DF90CF90BF90AF909F908F907F909F +:1049E0006F905F904F903F902F900895CF92DF92FD +:1049F000EF92FF920F931F93CF93DF93CDB7DEB764 +:104A0000CC54D1090FB6F894DEBF0FBECDBF8C01D8 +:104A10006B016CE172E0CE01895B9F4F0E94421BEB +:104A2000F601E480F5806CE172E0CE018F5B9F4F70 +:104A30000E94421BFCE1EF16F104B9F52BE1E22ED6 +:104A4000F12CB701C6010E94211AFC016081CE0140 +:104A500001960E94101BBE016F5F7F4FCE018F5BDE +:104A60009F4F0E94D21ACE0101960E940B1B61E259 +:104A700074E0CE018F5B9F4F0E94331A6DE872E0A5 +:104A8000811109C0CE018F5B9F4F0E94331A88238A +:104A900039F061E274E0CE01895B9F4F0E94AC1A4D +:104AA000F1E0EF1AF10868F676C0E0E2EE16F104E4 +:104AB000B9F59FE1E92EF12CB701C6010E94211A38 +:104AC000FC016081CE0101960E94101BBE016F5F48 +:104AD0007F4FCE018F5B9F4F0E94D21ACE0101966D +:104AE0000E940B1B61E274E0CE018F5B9F4F0E941E +:104AF000331A6DE872E0811109C0CE018F5B9F4FC0 +:104B00000E94331A882339F061E274E0CE01895B98 +:104B10009F4F0E94AC1AF1E0EF1AF10868F63BC013 +:104B2000E4E0EE16F10409F04CC083E0E82EF12C2D +:104B3000B701C6010E94211AFC016081CE010196D5 +:104B40000E94101BBE016F5F7F4FCE018F5B9F4F96 +:104B50000E94D21ACE0101960E940B1B61E274E002 +:104B6000CE018F5B9F4F0E94331A6DE872E0811176 +:104B700009C0CE018F5B9F4F0E94331A882339F002 +:104B800061E274E0CE01895B9F4F0E94AC1AF1E0B4 +:104B9000EF1AF10868F642E050E060E070E0299614 +:104BA0008EAD9FAD29970E94672E20E1AE014F5F29 +:104BB0005F4F0E94CB2FBE016F5F7F4FC8010E94E5 +:104BC000421BCE018F5B9F4F0E940B1BCE01895B66 +:104BD0009F4F0E940B1BC801C45BDF4F0FB6F894B8 +:104BE000DEBF0FBECDBFDF91CF911F910F91FF9020 +:104BF000EF90DF90CF9008958F929F92AF92BF92E7 +:104C0000CF92DF92EF92FF920F931F93CF93DF9398 +:104C1000CDB7DEB76E970FB6F894DEBF0FBECDBF2F +:104C20000E940D176B017C0180918B0790918C077E +:104C30009601281B390BC90130938A0720938907F5 +:104C400020918707309188072C39310508F4FFC07F +:104C50002091F7053091F805A901405A5F404817A7 +:104C6000590708F0F4C02056304F8217930708F018 +:104C7000EEC020912706309128062D5A3D40273E50 +:104C8000334008F0E4C06CE172E0CE0149960E9426 +:104C9000421B6CE172E0CE0143960E94421B6CE124 +:104CA00072E0CE010D960E94421B09E216E0F80167 +:104CB00020813181828193812817390718F461E2BC +:104CC00074E005C08217930730F46DE872E0CE01FE +:104CD00043960E94AC1A0C5F1F4FF6E0093A1F077B +:104CE00031F709EA16E0F801208131818281938150 +:104CF0002817390718F461E274E005C0821793079A +:104D000030F46DE872E0CE0149960E94AC1A0C5F57 +:104D10001F4FF7E009311F0731F709E117E0F801EC +:104D200020813181828193812817390718F461E24B +:104D300074E005C08217930730F46DE872E0CE018D +:104D40000D960E94AC1A0C5F1F4FF7E009321F0747 +:104D500031F7BE01635F7F4FCE0107960E94281B8B +:104D6000BE01695F7F4FCE0101960E94F624BE010D +:104D70006F5F7F4F84E995E00E94D21ACE010196C1 +:104D80000E940B1BCE0107960E940B1BBE016D5E9D +:104D90007F4FCE0107960E94281BBE01695F7F4F9F +:104DA000CE0101960E94F624BE016F5F7F4F8AE913 +:104DB00095E00E94D21ACE0101960E940B1BCE01F3 +:104DC00007960E940B1BBE01675E7F4FCE010796C0 +:104DD0000E94281BBE01695F7F4FCE0101960E9491 +:104DE000F624BE016F5F7F4F80EA95E00E94D21AE1 +:104DF000CE0101960E940B1BCE0107960E940B1B51 +:104E0000812C912C540183948092620590926305C9 +:104E1000A0926405B092650584E090E09093F4055B +:104E20008093F305CE010D960E940B1BCE01439695 +:104E30000E940B1BCE0149960E940B1B80926205BB +:104E400090926305A0926405B092650503C0893C09 +:104E5000924320F01092880710928707809187076D +:104E600090918807883C910540F010928807109235 +:104E700087071092F6051092F505809187079091AB +:104E800088079C012F5F3F4F309388072093870747 +:104E9000880F991FFC01E950FA4F80918907909182 +:104EA0008A0791838083C0928B07D0928C07E0920F +:104EB0008D07F0928E076E960FB6F894DEBF0FBE88 +:104EC000CDBFDF91CF911F910F91FF90EF90DF90B9 +:104ED000CF90BF90AF909F908F9008950F931F93A6 +:104EE000CF93DF931F92CDB7DEB78B0180914E0534 +:104EF000811107C08DE395E00E94351981E0809310 +:104F00004E0582E0898341E050E0BE016F5F7F4F34 +:104F1000809140050E946C1797FD08C08091400564 +:104F200048E050E0B80180640E946C170F90DF9158 +:104F3000CF911F910F910895DC01683810F06858E7 +:104F40002DC0E62FF0E067FF11C0E058F10981E0C5 +:104F500090E001C0880FEA95EAF714969C911497A7 +:104F6000892B14968C93149760E018C0EF5CFD4F6A +:104F70006491611109C081E090E013969C938E9337 +:104F8000129780E090E0089567FF08C014968C9116 +:104F90001497826014968C9314976F7716968C9161 +:104FA0001697861751F117968C911797861729F146 +:104FB00018968C911897861701F119968C9119976C +:104FC0008617D9F01A968C911A978617B1F01B960E +:104FD0008C911B97861789F0FD01369680E090E052 +:104FE0002191211105C0FD01E80FF91F668305C05D +:104FF000019686309105A1F7BECFCD01BD016C5F52 +:105000007F4F0E946E2781E090E00895EF92FF921B +:105010000F931F93CF938C01C62F0E949C277C0176 +:10502000C83818F068E76C0F1FC0EC2FF0E0C7FF1E +:105030000FC0E058F10921E030E001C0220FEA95ED +:10504000EAF72095F80184812823248360E00CC0CE +:10505000EF5CFD4F64916623D1F067FF05C0F80156 +:1050600084818D7F84836F77F801369686E066238E +:1050700021F09081961301C01082815031968111E8 +:10508000F6CFB8016C5F7F4FC8010E946E27C70141 +:105090009927CF911F910F91FF90EF900895CF9393 +:1050A000DF93CDB7DEB7E0970FB6F894DEBF0FBE43 +:1050B000CDBF789484B5826084BD84B5816084BDA1 +:1050C00085B5826085BD85B5816085BD80916E00A6 +:1050D000816080936E0010928100809181008260D7 +:1050E0008093810080918100816080938100809114 +:1050F0008000816080938000809191008260809325 +:105100009100809191008160809391008091900046 +:105110008160809390008091C10084608093C10081 +:105120008091C10082608093C1008091C100816044 +:105130008093C1008091C30081608093C3008091FF +:10514000C00082608093C0008091C2008160809323 +:10515000C20080917A00846080937A0080917A0006 +:10516000826080937A0080917A00816080937A00D7 +:1051700080917A00806880937A001092490410929E +:105180003104109230048091D70081608093D70061 +:1051900080EA8093D80089B5806189BD89B5826035 +:1051A00089BD09B400FEFDCF61E070E080E090E0D1 +:1051B0000E9432178091D8008F7C80618093D80044 +:1051C0008091E000807F8093E0008091E1008E7EFE +:1051D0008093E1008DE08093E200559A209A5D98DB +:1051E0002898EEEFFFE7859194918B3F9C4D19F441 +:1051F00081E080932F04E0916004F091610482E0EB +:105200008083E0915C04F0915D041082E0915E0483 +:10521000F0915F048FEC808310926804E091640445 +:10522000F091650486E08083E0916204F09163046C +:10523000808180618083E0916204F09163048081C9 +:1052400088608083E0916204F091630480818068CB +:105250008083E0916204F091630480818F7D80837C +:1052600060ED77E080E090E00E94321761E082E13B +:105270000E94D11661E083E10E94D11661E085E1D0 +:105280000E94D11661E084E10E94D11660E082E0C4 +:105290000E94D11661E085E10E94A11660E084E1E0 +:1052A0000E94A11661E085E10E94A11660E084E100 +:1052B0000E94A11661E085E10E94D11661E084E1BF +:1052C0000E94D11660E082E00E94D11661E088E081 +:1052D0000E94D11661E088E00E94A11660E085E09E +:1052E0000E94D11661E086E00E94D11661E089E05B +:1052F0000E94D11660E086E00E94A11660E089E07D +:105300000E94A11664E670E080E090E00E943217EF +:1053100060E173E080E594E00E94E2150E948E2037 +:1053200064E070E080E090E00E94321761E383E285 +:1053300093E00E942B0E6AE086E293E00E942B0E1F +:1053400043E050E06DE089E293E00E94D61262E211 +:105350008EE293E00E942B0E42E050E060E189E390 +:1053600093E00E94D61241E050E068E083E493E0CD +:105370000E94D61281E090E09093800580937F0593 +:105380000E941411ABEF2A2EA4E03A2E0E941C18A2 +:105390004B015C010E941C18DC01CB0188199909A2 +:1053A000AA09BB0985369105A105B10508F06FC0B2 +:1053B00009EE13E00E944B11892B19F401501109D9 +:1053C000C9F7C1010197F1F70E944B11019711F73D +:1053D00018E0F9EEAF2EF3E0BF2E0E944B110197BB +:1053E00029F431E0A31AB108C1F751C0C1010197F6 +:1053F000F1F70E944B11892B09F449C0115049F76C +:1054000009EE13E00E944B11019709F485C2512C5B +:105410001D821C821B821A82198200E010E030E09B +:10542000AE014F5F5F4F5A01412C60E0C10101970F +:10543000F1F738AB6DA70E944B1121E038A96DA59B +:10544000892B09F420E0822E912C643009F06BC284 +:10545000420ED5018C91280FF50121935F0149EE91 +:10546000642E43E0742E38AB6DA70E944B1138A90F +:105470006DA58815990509F46BC251106EC26F5F56 +:105480006530A1F63A3009F46DC240FE69C28091E0 +:10549000320490913304009709F49EC08130910545 +:1054A000D1F0029709F085C08091380490913904B9 +:1054B000A0913A04B0913B0489A79AA7ABA7BCA7D7 +:1054C0004090340450903504609036047090370456 +:1054D0000FE010E00FC040913E0450913F046091F6 +:1054E00040047091410480913C0490913D040E94DD +:1054F000CE115FC080903E0490903F04A090400485 +:10550000B0904104B501A40180913C0490913D0408 +:105510000E94CE110150110969F7A50194012419C7 +:10552000350946095709A4E6B0E00E94933229A53F +:105530003AA54BA55CA524193509460957090E94CF +:10554000743263E673E080E594E02DA738AB4EA794 +:105550005FA70E94F6152DA538A9B901653671051A +:1055600014F064E670E04AE050E080E594E00E94C8 +:10557000C91580913E0490913F04A0914004B091E0 +:10558000410429A53AA54BA55CA582179307A4075A +:10559000B50721F410923304109232040196A11D34 +:1055A000B11D80933E0490933F04A0934004B093B8 +:1055B000410480E594E00E94A713181619060CF028 +:1055C00066CF109233041092320463E773E080E5F3 +:1055D00094E00E94E2155BCF80E594E00E94A7135F +:1055E00018161906B4F480E594E00E9485138983A7 +:1055F0001A8241E050E0BE016F5F7F4F8EE895E078 +:105600000E94521A64E070E080E090E00E9432173D +:10561000E3CF8091920590919305892B11F00E9420 +:10562000850180910A0190910B018130910509F06B +:10563000BCC08091660590916705A0916805B09106 +:105640006905892B8A2B8B2B09F463C10E941C18D6 +:105650000091440410914504209146043091470480 +:10566000DC01CB01801B910BA20BB30B8E3591405B +:10567000A105B10548F410926605109267051092D5 +:1056800068051092690545C168E773E080E594E01C +:105690000E94F61560910601709107018091080142 +:1056A000909109011CA21BA21EA21DA218A61FA256 +:1056B0002AE0AE014F5F5F4F0E94B42FBE016F5FC3 +:1056C0007F4FCE0183960E94BB1A23E030E040E07A +:1056D00050E0BE016D5D7F4FCE0101960E94571BC9 +:1056E000BE016F5F7F4F80E594E00E940F15CE01F1 +:1056F00001960E940B1BCE0183960E940B1B6BE848 +:1057000073E080E594E00E94F615409142045091C8 +:10571000430460E070E02AE080E594E00E943215E6 +:105720006CE973E080E594E00E94F615409166050F +:105730005091670560916805709169054F70552714 +:105740006627772720E180E594E00E9432156CE51A +:1057500073E080E594E00E94F615809166059091D3 +:105760006705A0916805B0916905BC01CD0124E0F1 +:1057700096958795779567952A95D1F740E150E002 +:105780000E945E0F109266051092670510926805E0 +:10579000109269050E941C1860934404709345049C +:1057A0008093460490934704B4C0029709F0B1C0B7 +:1057B0008091620590916305A0916405B0916505A3 +:1057C000892B8A2B8B2B09F4A4C0E99881E994E1F9 +:1057D00090930F0180930E016AE975E0CE01019666 +:1057E0000E94281B40E150E060E070E089819A81CE +:1057F0000E94672ECE0101960E940B1B62EB73E0A4 +:1058000080E594E00E94F61565E873E080E594E099 +:105810000E94F615609106017091070180910801C0 +:10582000909109011CA21BA21EA21DA218A61FA2D4 +:105830002AE0AE014F5F5F4F0E94B42FBE016F5F41 +:105840007F4FCE0183960E94BB1A23E030E040E0F8 +:1058500050E0BE016D5D7F4FCE0101960E94571B47 +:10586000BE016F5F7F4F80E594E00E940F15CE016F +:1058700001960E940B1BCE0183960E940B1B60ECCD +:1058800073E080E594E00E94F6156DE573E080E535 +:1058900094E00E94F6156AE975E0CE0101960E9437 +:1058A000281BBE016F5F7F4F80E594E00E940F15BB +:1058B000CE0101960E940B1B61EE73E080E594E03F +:1058C0000E94F61560EA75E0CE0101960E94281B41 +:1058D000BE016F5F7F4F80E594E00E940F15CE01FF +:1058E00001960E940B1B6CE172E080E594E00E943F +:1058F000E2151092620510926305109264051092F1 +:10590000650581E090E090936B0580936A050E94A5 +:10591000430F0E9447143ACD0150110909F072CD8E +:105920005524539475CD3A3009F492CD323048F075 +:10593000CC0CDD1CEE1CFF1CC20ED11CE11CF11CAA +:1059400087CDA801440F551F8A01080D191D80CD70 +:10595000F1E06F1A710809F086CD5524539492CD69 +:10596000511095CD3F5F3B3009F05ACD51108FCD8E +:10597000898180FD8CCD8A8180FD89CD8B8180FDE0 +:1059800086CD8C8180FD83CD11270E941C188090CC +:10599000440490904504A0904604B0904704DC0174 +:1059A000CB0188199909AA09BB098E359140A10537 +:1059B000B10508F46CCDC114D104E104F10409F47B +:1059C00066CD6DE473E080E594E00E94F615A801D1 +:1059D000110F660B770B2AE030E080E594E00E941F +:1059E0007B156CE573E080E594E00E94F6154AE0D3 +:1059F00050E0C701B6010E945E0F0E941C18609320 +:105A00004404709345048093460490934704C12C4A +:105A1000D12C76013CCD86EB95E00E940B1B8EE8E5 +:105A200095E00E940B1B84E995E00E940B1B8AE91C +:105A300095E00E940B1B80EA95E00C940B1B0F93E2 +:105A40001F93CF93DF93109253041092520488EE69 +:105A500093E0A0E0B0E08093540490935504A093A9 +:105A60005604B093570427E431E030935104209357 +:105A700050042DEC30E030935D0420935C042CEC5A +:105A800030E030935F0420935E0428EC30E03093E4 +:105A900061042093600429EC30E030936304209388 +:105AA00062042AEC30E030936504209364042EEC09 +:105AB00030E03093670420936604109269041092DA +:105AC0006A0410926B0410926C041092F00410920D +:105AD000EF048093F1049093F204A093F304B09345 +:105AE000F40489E591E09093EE048093ED048FEF48 +:105AF0009FEF9093FA048093F90410925905109245 +:105B000058058BE691E09093570580935605809158 +:105B1000AE05811113C01092A9051092A80585E366 +:105B200091E09093AB058093AA058FE290E090936B +:105B3000AD058093AC0581E08093AE0580914E0564 +:105B4000811107C08DE395E00E94351981E08093B3 +:105B50004E05E0914805F0914905309739F488EAFF +:105B600095E090934905809348050AC08081918112 +:105B7000009711F0FC01FACF88EA95E091838083C9 +:105B80002091AC053091AD0580914A0590914B056F +:105B9000820F931F90934B0580934A056CE172E04E +:105BA00080EA95E00E94421B6CE172E08AE995E090 +:105BB0000E94421B6CE172E084E995E00E94421B66 +:105BC0006CE172E08EE895E00E94421BCFEFDFEFC0 +:105BD000D0938205C09381050AE010E010938405FC +:105BE0000093830549E050E064E671E085E895E0C4 +:105BF0000E94A02FD0938005C0937F058CE390E096 +:105C00009093190180931801109266051092670510 +:105C1000109268051092690510937605009375053A +:105C200022E030E03093780520937705D0936D051E +:105C3000C0936C0524E030E030937105209370052B +:105C400021E02093720525EF30E030936F0520931B +:105C50006E05D0936B05C0936A05909317018093EE +:105C6000160110926205109263051092640510925D +:105C7000650583E190E09093BD058093BC0582E1CA +:105C800090E09093BF058093BE051092C20580E21C +:105C90008093C3051092C40585E08093CA0585E012 +:105CA00090E0A0E0B0E08093D0059093D105A09360 +:105CB000D205B093D3051092C5056CE172E086EB76 +:105CC00095E0DF91CF911F910F910C94421BA6E0BC +:105CD000B0E0EDE6FEE20C949E325C016B017A01CD +:105CE0006115710519F0DB018D939C93E114F104AA +:105CF00029F0C7010297839708F0DCC03501BFEF98 +:105D00006B1A7B0AF5011081812F90E00E94972F7A +:105D1000892B11F05301F2CF1D3249F43501F2E025 +:105D20006F0E711CD50111961C9101E009C01B3248 +:105D300031F43501B2E06B0E711CF501118100E008 +:105D4000E114F10409F4C4C0F0E1EF16F10489F4A0 +:105D5000103399F5D3018C918F7D883509F0B2C04D +:105D600011961C91B2E06B0E711C026050E1E52EA1 +:105D7000F12CEAE0EE16F10409F4B0C0F0E1EF1600 +:105D8000F104D9F028E0E216F10451F438E0E32EF2 +:105D9000F12C88248A94982CA82C4FE1B42E13C09F +:105DA0006FEF7FEFCB0197010F2C000C440B550BCD +:105DB0000E94523249015A0106C088248A94982CC4 +:105DC000A82C2FE0B22E7E826D8260E020E030E0D1 +:105DD000A90127010F2C000C660877082D803E8052 +:105DE000E0EDE10FEA3060F08FEB810F8A3110F4C3 +:105DF000E9EC05C08FE9810F8A3190F5E9EAE10FFE +:105E00008E2F90E08E159F055CF56F3F09F182168D +:105E10009306A406B506D8F0C301B2010E9442322F +:105E20002E2F30E040E050E029833A834B835C839F +:105E3000260F371F481F591F89819A81AB81BC816A +:105E4000281739074A075B0710F061E001C06FEFC0 +:105E5000ED81FE813196FE83ED83D1011C91BECF91 +:105E6000C114D10489F0662339F08D819E81019798 +:105E7000F6019183808308C001FF06C08D819E8159 +:105E80000297D6018D939C9300FF07C050954095D3 +:105E9000309521953F4F4F4F5F4F67FF10C082E213 +:105EA00090E09093200880931F086FEF7FEF8FEFB3 +:105EB0009FEF1BC060E070E080E090E016C0B90189 +:105EC000CA0113C010E3E114F10409F45FCF51CF0C +:105ED000103309F43FCF9AE0E92EF12C89E9882E9E +:105EE000982CA82C89E1B82E6ECF2696E2E10C946E +:105EF000BA32FC0188279927E89421912032E9F3EE +:105F0000293010F02E30C8F32B3241F02D3239F405 +:105F1000689404C00E94C32F820F911D21912053C9 +:105F20002A30C0F31EF4909581959F4F08959111EA +:105F30000C943431803219F089508550C8F7089597 +:105F4000FB01DC0102C005900D9241505040D8F792 +:105F50000895BB274A3031F4992322F4BDE290958D +:105F600081959F4F0C94EE2FBB272A3051F4992333 +:105F700042F4BDE290958095709561957F4F8F4F6B +:105F80009F4F0C94CC2F7AE0979F902D879F802D68 +:105F9000910D11240895BB27FA01A62F62177105F0 +:105FA00081059105330B30FB66F0AA27660F771F3A +:105FB000881F991FAA1FA21710F0A21B63953850C3 +:105FC000A9F7A05DAA3308F0A95DA19336F7B11136 +:105FD000B1931082CA010C943731BB27FB015527BE +:105FE000AA27880F991FAA1FA41710F0A41B839536 +:105FF0005051B9F7A05DAA3308F0A95DA1930097AD +:1060000079F7B111B1931192CB010C943731CF9341 +:10601000DF938230910510F482E090E0E091230854 +:10602000F091240820E030E0C0E0D0E0309711F19A +:106030004081518148175907C0F04817590761F44A +:1060400082819381209719F09B838A832BC0909340 +:1060500024088093230826C02115310519F0421722 +:10606000530718F49A01BE01DF01EF010280F381AA +:10607000E02DDCCF2115310509F1281B390B243027 +:10608000310590F412968D919C91139761157105CD +:1060900021F0FB019383828304C0909324088093B2 +:1060A0002308FD01329644C0FD01E20FF31F8193E6 +:1060B0009193225031092D933C933AC020912108AD +:1060C00030912208232B41F420912F01309130018F +:1060D000309322082093210820912D0130912E0128 +:1060E0002115310541F42DB73EB740913101509152 +:1060F0003201241B350BE0912108F0912208E217B0 +:10610000F307A0F42E1B3F0B2817390778F0AC01DA +:106110004E5F5F4F2417350748F04E0F5F1F5093B7 +:106120002208409321088193919302C0E0E0F0E0BF +:10613000CF01DF91CF9108950F931F93CF93DF93FA +:10614000009709F48CC0FC013297138212820091EF +:106150002308109124080115110581F42081318153 +:10616000820F931F209121083091220828173907A8 +:1061700079F5F0932208E093210871C0D80140E03E +:1061800050E0AE17BF0750F412962D913C91139733 +:10619000AD012115310509F1D901F3CF9D01DA01D6 +:1061A0003383228360817181860F971F8217930743 +:1061B00069F4EC0128813981260F371F2E5F3F4F8C +:1061C000318320838A819B8193838283452B29F4A9 +:1061D000F0932408E093230842C01396FC93EE93B7 +:1061E0001297ED01499159919E01240F351FE21735 +:1061F000F30771F480819181840F951F02961196A7 +:106200009C938E938281938113969C938E93129785 +:10621000E0E0F0E0D80112968D919C9113970097E1 +:1062200019F0F8018C01F6CF8D919C9198012E5FA9 +:106230003F4F820F931F2091210830912208281789 +:10624000390769F4309729F4109224081092230832 +:1062500002C0138212821093220800932108DF915A +:10626000CF911F910F910895992788270895DC01F8 +:10627000FC01672F71917723E1F7329704C07C917D +:106280006D9370836291AE17BF07C8F30895E894C9 +:1062900009C097FB3EF490958095709561957F4F6E +:1062A0008F4F9F4F9923A9F0F92F96E9BB2793951C +:1062B000F695879577956795B795F111F8CFFAF42C +:1062C000BB0F11F460FF1BC06F5F7F4F8F4F9F4F5D +:1062D00016C0882311F096E911C0772321F09EE8BB +:1062E000872F762F05C0662371F096E8862F70E021 +:1062F00060E02AF09A95660F771F881FDAF7880FFB +:106300009695879597F908950E9497310C940832D5 +:106310000E94FA3138F00E94013220F0952311F0EA +:106320000C94F1310C94F73111240C943C320E94FE +:10633000193270F3959FC1F3950F50E0551F629F7E +:10634000F001729FBB27F00DB11D639FAA27F00DCE +:10635000B11DAA1F649F6627B00DA11D661F829FF5 +:106360002227B00DA11D621F739FB00DA11D621FDA +:10637000839FA00D611D221F749F3327A00D611DF7 +:10638000231F849F600D211D822F762F6A2F1124D9 +:106390009F5750409AF0F1F088234AF0EE0FFF1F0C +:1063A000BB1F661F771F881F91505040A9F79E3F63 +:1063B000510580F00C94F1310C943C325F3FE4F3D2 +:1063C000983ED4F3869577956795B795F795E795B9 +:1063D0009F5FC1F7FE2B880F911D9695879597F9C2 +:1063E000089597F99F6780E870E060E008959FEF57 +:1063F00080EC089500240A9416161706180609065C +:10640000089500240A94121613061406050608952A +:10641000092E0394000C11F4882352F0BB0F40F4B2 +:10642000BF2B11F460FF04C06F5F7F4F8F4F9F4FF2 +:10643000089557FD9058440F551F59F05F3F71F074 +:106440004795880F97FB991F61F09F3F79F08795DB +:106450000895121613061406551FF2CF4695F1DF64 +:1064600008C0161617061806991FF1CF86957105F4 +:10647000610508940895E894BB2766277727CB0128 +:1064800097F90895DB018F939F930E949332BF91F8 +:10649000AF91A29F800D911DA39F900DB29F900D73 +:1064A00011240895A1E21A2EAA1BBB1BFD010DC0E9 +:1064B000AA1FBB1FEE1FFF1FA217B307E407F507B4 +:1064C00020F0A21BB30BE40BF50B661F771F881F90 +:1064D000991F1A9469F760957095809590959B0126 +:1064E000AC01BD01CF010895052E97FB1EF4009469 +:1064F0000E948B3257FD07D00E94523207FC03D016 +:106500004EF40C948B3250954095309521953F4F29 +:106510004F4F5F4F089590958095709561957F4F8F +:106520008F4F9F4F08950E94D532A59F900DB49F25 +:10653000900DA49F800D911D112408952F923F92DC +:106540004F925F926F927F928F929F92AF92BF9283 +:10655000CF92DF92EF92FF920F931F93CF93DF932F +:10656000CDB7DEB7CA1BDB0B0FB6F894DEBF0FBE8C +:10657000CDBF09942A88398848885F846E847D84D9 +:106580008C849B84AA84B984C884DF80EE80FD80DB +:106590000C811B81AA81B981CE0FD11D0FB6F89451 +:1065A000DEBF0FBECDBFED010895A29FB001B39F26 +:1065B000C001A39F700D811D1124911DB29F700D0C +:1065C000811D1124911D08950E94F8320C94083207 +:1065D0000E94013258F00E94FA3140F029F45F3FE6 +:1065E00029F00C94F13151110C943C320C94F73198 +:1065F0000E94193268F39923B1F3552391F3951B47 +:10660000550BBB27AA2762177307840738F09F5FD3 +:106610005F4F220F331F441FAA1FA9F335D00E2E40 +:106620003AF0E0E832D091505040E695001CCAF7AD +:106630002BD0FE2F29D0660F771F881FBB1F261770 +:1066400037074807AB07B0E809F0BB0B802DBF0147 +:10665000FF2793585F4F3AF09E3F510578F00C9416 +:10666000F1310C943C325F3FE4F3983ED4F38695CD +:1066700077956795B795F7959F5FC9F7880F911D37 +:106680009695879597F90895E1E0660F771F881F23 +:10669000BB1F621773078407BA0720F0621B730BD6 +:1066A000840BBA0BEE1F88F7E09508950E94213203 +:1066B00088F09F5798F0B92F9927B751B0F0E1F0C3 +:1066C000660F771F881F991F1AF0BA95C9F714C073 +:1066D000B13091F00E943B32B1E008950C943B320E +:1066E000672F782F8827B85F39F0B93FCCF38695AC +:1066F00077956795B395D9F73EF490958095709509 +:1067000061957F4F8F4F9F4F0895AA1BBB1B51E18F +:1067100007C0AA1FBB1FA617B70710F0A61BB70B11 +:10672000881F991F5A95A9F780959095BC01CD01B6 +:106730000895EE0FFF1F0590F491E02D09940F933B +:10674000083090F0982F872F762F652F542F432FE6 +:10675000322F22270850F4CF220F331F441F551F1A +:10676000661F771F881F991F0A95B2F70F9108952A +:1067700097FB10F8169400080F93083098F0085013 +:10678000232F342F452F562F672F782F892F902DA9 +:10679000F4CF059497958795779567955795479585 +:1067A000379527950A95AAF70F9108952A0D3B1D55 +:1067B0004C1D5D1D6E1D7F1D801F911F08950024BF +:1067C000A7FD00942A1730054005500560057005A7 +:1067D000800590050895A0E0B0E0E1EFF3E30C94AC +:1067E000A232EC01009721F4CB010E940730B8C01F +:1067F000FC01E60FF71F9C0122503109E217F30755 +:1068000008F4ACC0D9010D911C9111970617170718 +:10681000B0F00530110508F49FC0C8010497861731 +:10682000970708F499C002501109061B170B019332 +:1068300011936D937C93CF010E949C308DC05B01BE +:10684000A01AB10A4C01800E911EA0912308B091AC +:10685000240840E050E0E12CF12C109709F44AC0E4 +:10686000A815B905D1F56D907C901197630182E070 +:10687000C80ED11CCA14DB0480F1A3014A195B09BC +:106880006A0182E0C80ED11C1296BC901297139632 +:10689000AC91B5E0CB16D10440F0B282A383518312 +:1068A0004083D9016D937C930AC00E5F1F4FC301D3 +:1068B000800F911FF90191838083EB2DFA2FE11452 +:1068C000F10431F0D7011396FC93EE93129744C074 +:1068D000F0932408E09323083FC08D919C91119779 +:1068E0004817590708F4AC017D0112960D90BC9130 +:1068F000A02DB3CF80912108909122088815990589 +:10690000E1F446175707C8F480912D0190912E01AC +:10691000009741F48DB79EB74091310150913201FB +:10692000841B950BE817F907C8F4F0932208E0934D +:106930002108F901718360830FC0CB010E940730E9 +:106940007C01009759F0A801BE010E94BA34CE0123 +:106950000E949C30C70104C0CE0102C080E090E0DC +:10696000CDB7DEB7EEE00C94BE3281E090E0F89453 +:106970000C94F834FB01DC0102C001900D924150EF +:106980005040D8F70895FC018191861721F08823A3 +:10699000D9F7992708953197CF010895FB01DC01BC +:1069A0008D91019080190110D9F3990B0895FB0185 +:1069B000DC0101900D920020E1F70895FB01519157 +:1069C0005523A9F0BF01DC014D9145174111E1F7B5 +:1069D00059F4CD010190002049F04D91401541112D +:1069E000C9F3FB014111EFCF81E090E001970895D9 +:1069F00011E0CAE5D1E004C0FE010E94993321965E +:0A6A0000CB35D107C9F7F894FFCF9A +:106A0A00FFFF0018DD19C084C61201009114911409 +:106A1A009114911491143C003C0000C18081000043 +:106A2A0000FFFFFFFF00E10000000000000000255A +:106A3A00088000E0B94C264080140000C000000025 +:106A4A0000000000000000DE134B1376132514A784 +:106A5A001385139913000000005114061872146765 +:106A6A00147714B61492140000000006284B130879 +:106A7A0023072300000000BD224B230B23E42248F6 +:106A8A004944005B4849445D6C6F636B005B48494D +:106A9A00445D636D61747269780068696400524686 +:106AAA00004A616D002C6672657100636C617373D4 +:106ABA0000536D617274002C6672657132006672E1 +:106ACA0065713100527564650054504D530054503D +:106ADA004D535F6F6B005472616E736D6974004C35 +:106AEA0069677468426172002C64617461002A5497 +:106AFA0072616E736D6974204C6967746842617261 +:106B0A002000467265713A002C446174613A002A89 +:106B1A005472616E736D697420000D0A00417474B9 +:106B2A0061636B002C7374617274002C656E64006F +:106B3A002C66756E630053746172743A002C456E4C +:106B4A00643A002C46756E633A005B52465D5B50B0 +:106B5A00726F67726573735D005377697463680057 +:106B6A00616374696F6E002A52465F506F7765726F +:106B7A00206F6666002A52465F506F776572206FF3 +:106B8A006E00536574757000434331313031002A09 +:106B9A0052465F736E69666665725F666978656498 +:106BAA00006B65656C6F71002A52465F736E696689 +:106BBA006665725F4B65656C6F71006E5246323462 +:106BCA004C3031004E46430073696D756C617469CF +:106BDA006F6E0076640061747461636B003B53747A +:106BEA006172742049443A003B454E442049443A74 +:106BFA000073776974636800777269746500772C2B +:106C0A0056443A006572726F723A002020202000C2 +:106C1A00437562656D696E692052756E696E672E7D +:106C2A002E2E0076720043480046524551004D6FA1 +:106C3A0064756C6174696F6E00446174612052619D +:106C4A00746500504B544354524C3020005B4E46FE +:106C5A00435D5B726561645D76643A002C646174BD +:106C6A00613A005B4E46435D5B70726F6772657393 +:106C7A00735D0065786974005B52465D5B536E69AB +:106C8A00666665725D667265713A002C70726F7421 +:106C9A006F636F6C3A46697865642D002C6D6F647A +:106CAA00756C6174696F6E3A61736B2C66756E638D +:106CBA003A005B52465D5B536E69666665725D00BB +:106CCA002C70726F746F636F6C3A6B65656C6F7161 +:106CDA002C6D6F64756C6174696F6E3A61736B2C9D +:106CEA00002C53657269616C4E756D6265723A006B +:106CFA005B52465D5B4A616D5D525353493A00648B +:106D0A00422C465245513A004D687A005B52465D24 +:106D1A005B4A616D5D4E6F74204A616D6D696E6785 +:046D2A000030000035 +:00000001FF diff --git a/Software/ATmega32U4_nl/ATmega32U4_nl.ino.with_bootloader.micro.hex b/Software/ATmega32U4_nl/ATmega32U4_nl.ino.with_bootloader.micro.hex new file mode 100644 index 0000000..efdc682 --- /dev/null +++ b/Software/ATmega32U4_nl/ATmega32U4_nl.ino.with_bootloader.micro.hex @@ -0,0 +1,1876 @@ +:100000000C945B010C940E190C94E7180C94C01816 +:100010000C9499180C9483010C9483010C9472181D +:100020000C9483010C9483010C949D1B0C94681C0C +:100030000C9483010C9483010C9483010C94830130 +:100040000C9483010C9483010C9483010C94830120 +:100050000C9483010C9483010C9483010C94281854 +:100060000C9483010C9432160C940C160C9483019E +:100070000C9483010C9483010C9483010C948301F0 +:100080000C9483010C9483010C9483010C948301E0 +:100090000C9483010C9483010C9483010C948301D0 +:1000A0000C9483010C9483010C9483017C167F16BD +:1000B0006E1672167816A016A016A016831687164E +:1000C0008B1691169516A0169B16000000002300B3 +:1000D000260029002C002F00040404040403040556 +:1000E00002020202040302020202060606060606D5 +:1000F00004040202020404040802011040804010BB +:10010000204080408008020401804020100201103D +:100110008010204040200000000200090F00000372 +:100120000401000C000000000000000000000000BE +:10013000000000000005010906A10185020507195C +:10014000E029E715002501750195088102950175E3 +:10015000088103950675081500256505071900290E +:10016000658100C05E01011F01030301008A0201D5 +:100170000A010202010064001E47040B0906007C0C +:100180000101060103030100F401060E0102020150 +:1001900000C201170101020201019600023E0106A0 +:1001A00006010000000000240027002A002D003076 +:1001B0000000000000250028002B002E0031000860 +:1001C0000B0002020201000904000001020200000B +:1001D0000524001001052401010104240206052460 +:1001E0000600010705810310004009040100020A0E +:1001F00000000007050202400000070583024000DE +:10020000000403090412010002EF020140412337F8 +:100210008000010102030141726475696E6F204C18 +:100220004C430041726475696E6F204D6963726F53 +:100230000000000000000000002A2B280000000041 +:1002400000000000000000000000000000000000AE +:10025000002C9EB4A0A1A2A434A6A7A5AE362D372B +:1002600038271E1F20212223242526B333B62EB77C +:10027000B89F8485868788898A8B8C8D8E8F909194 +:1002800092939495969798999A9B9C9D2F3130A321 +:10029000AD350405060708090A0B0C0D0E0F1011E9 +:1002A00012131415161718191A1B1C1DAFB1B0B56F +:1002B00000001F2D0B2D11241FBECFEFDAE0DEBF93 +:1002C000CDBF14E0A0E0B1E0EAE0FAE602C005909C +:1002D0000D92A432B107D9F728E0A4E2B4E001C03E +:1002E0001D92A532B207E1F711E0CAE5D1E004C0E2 +:1002F0002197FE010E949933C935D107C9F70E94A1 +:100300004F280C94F8340C9400002F923F924F9297 +:100310005F926F927F928F929F92AF92BF92CF9295 +:10032000DF92EF92FF920F931F93CF93DF93CDB79E +:10033000DEB7E9970FB6F894DEBF0FBECDBF24E05D +:1003400030E041E050E06EE875E0CE0101960E9499 +:10035000571B6FE771E0CE0101960E94331A182FE8 +:10036000CE0101960E940B1B112309F4A7C063E87C +:1003700071E0CE0101960E94421BCE0101960E94BF +:100380002F118C01CE0101960E940B1B012BC9F489 +:1003900068E871E080E594E00E94E21563E886E594 +:1003A00095E00E949C276CE686E595E00E949C27DC +:1003B00068EE73E080E090E00E9432170E94760EB3 +:1003C0004EC06DE871E0CE0101960E94421BCE0145 +:1003D00001960E942F118C01CE0101960E940B1BE9 +:1003E000012B09F042C064E886E595E00E949C2755 +:1003F00062E886E595E00E949C2764E786E595E043 +:100400000E949C2768EC70E080E090E00E94321728 +:100410000E94760E6CED75E080E090E00E9432174D +:100420006CEC86E595E00E949C276CE271E080E030 +:1004300090E00E9432170E94760E6CE271E080E03C +:1004400090E00E94321762E971E086E595E00E9433 +:10045000F61564E670E080E090E00E94321760EBF1 +:1004600086E595E00E94062821C060E070E08EE8F5 +:1004700095E00E94211A2CE132E0DC012C932091BE +:1004800092053091930545E050E06EE875E0CE01AD +:1004900001960E94571BBE016F5F7F4F86E595E076 +:1004A0000E940F15CE0101960E940B1B6AE971E0B4 +:1004B00080E594E00E94E2150C940C0E23E030E0FD +:1004C00041E050E06EE875E0CE0101960E94571BB6 +:1004D0006EE971E0CE0101960E94331A182FCE0109 +:1004E00001960E940B1B112309F47AC761EA71E09F +:1004F000CE0101960E94421BCE0101960E942F114F +:100500008C01CE0101960E940B1B101611060CF0F7 +:10051000E1C065EA71E0CE0101960E94421BCE0166 +:1005200001960E942F118C016BEA71E0CE014B966F +:100530000E94421BCE014B960E942F11AC014A5FD4 +:100540005F4F98016EE875E0CE0189960E94571BB7 +:10055000CE014B960E940B1BCE0101960E940B1BF5 +:1005600061EB71E0CE0189960E94331A882309F469 +:100570006EC067EB71E0CE014B960E94421BCE012C +:100580004B960E942F118C016EEB71E0CE01839689 +:100590000E94421BCE0183960E942F11AC014A5F3C +:1005A0005F4F98016EE875E0CE0101960E94571BDF +:1005B0004AE050E060E070E089819A810E94672EF5 +:1005C00060932A0470932B0480932C0490932D0441 +:1005D000CE0101960E940B1BCE0183960E940B1B3D +:1005E000CE014B960E940B1B009192051091930532 +:1005F00068EB71E0CE014B960E94421BCE014B96F8 +:100600000E942F11AC014A5F5F4F98016EE875E0C0 +:10061000CE0101960E94571B4AE050E060E070E076 +:1006200089819A810E94672E609326047093270423 +:100630008093280490932904CE0101960E940B1BFD +:10064000CE014B960E940B1B81E090E03AC064EC17 +:1006500071E0CE0189960E94331A8823C1F100917E +:1006600092051091930566EA71E0CE014B960E94C7 +:10067000421BCE014B960E942F11AC014B5F5F4F86 +:1006800098016EE875E0CE0101960E94571B4AE082 +:1006900050E060E070E089819A810E94672E60934B +:1006A0000201709303018093040190930501CE0130 +:1006B00001960E940B1BCE014B960E940B1B82E001 +:1006C00090E090932504809324040E94B320CE01EF +:1006D000899631C569EC71E0CE0101960E94421BFA +:1006E000CE0101960E942F118C01CE0101960E942D +:1006F0000B1B101611060CF0BBC1FE0131966F01E9 +:100700000AE010E0E12CF12C809192059091930584 +:100710000817190708F085C0B8016F5F7F4F8EE892 +:1007200095E00E94211ADC016C91CE014B960E944B +:10073000101BB8018EE895E00E94211AFC0160812F +:10074000CE0189960E94101BBE01675D7F4FCE01CE +:1007500083960E94281BBE01655E7F4FCE01839663 +:100760000E94991ABC01CE018F960E94281BCE01CF +:1007700083960E940B1BCE0189960E940B1BCE0113 +:100780004B960E940B1B40E150E060E070E08FA5AB +:1007900098A90E94672E5601D6016C93B5E0EB161E +:1007A000F104A1F44AE050E060E070E08FA598A960 +:1007B0000E94672E0E9447312DEC3CEC4CE450E443 +:1007C0000E9484310E9456336E830EC0E6E0EE161E +:1007D000F10451F44AE050E060E070E08FA598A980 +:1007E0000E94672E695C6F836EE073E080E594E0A1 +:1007F0000E94F615FFEFCF1ADF0AD5014C9150E0A9 +:1008000060E070E020E180E594E00E943215BFEFE7 +:10081000EB1AFB0ACE018F960E940B1B0E5F1F4F37 +:1008200073CF6EEC71E080E594E00E94E2156CE11C +:1008300072E08EE895E00E94BB1A85E190E090930B +:1008400076058093750510922E0461E00E94D11602 +:100850000E94211060E082E00E94D11664E070E006 +:1008600080E090E00E9432170E94EC0F69E280E085 +:100870000E94870F6EE281E00E94870F66E082E0AF +:100880000E94870F67E483E00E94870F65E086E09F +:100890000E94870F64E087E00E94870F60E388E092 +:1008A0000E94870F61E983ED0E94D10F80917E0540 +:1008B000882331F060E089E00E94870F10927E0566 +:1008C00080917B05882331F060E08AE00E94870FE9 +:1008D00010927B0566E08BE00E94870F60E08CE061 +:1008E0000E94870F61E28DE00E94870F62E68EE032 +:1008F0000E94870F66E78FE00E94870F10927A05AB +:1009000068EF80E10E94870F6BE981E10E94870F09 +:1009100063E382E10E94870F62E283E10E94870F16 +:1009200068EF84E10E94870F60E085E10E94870FF5 +:1009300067E086E10E94870F60E387E10E94870FEE +:1009400068E188E10E94870F66E189E10E94870FD4 +:100950006CE68AE10E94870F63E08BE10E94870FBB +:1009600060E48CE10E94870F61E98DE10E94870FAE +:1009700067E88EE10E94870F6BE68FE10E94870F88 +:100980006BEF80E20E94870F66E581E20E94870F8D +:1009900061E182E20E94870F69EE83E20E94870F85 +:1009A0006AE284E20E94870F60E085E20E94870F7E +:1009B0006FE186E20E94870F61E487E20E94870F61 +:1009C00060E088E20E94870F69E589E20E94870F54 +:1009D0006FE78AE20E94870F6FE38BE20E94870F26 +:1009E00061E88CE20E94870F65E38DE20E94870F29 +:1009F0006BE08EE20E94870F0E94B50F60910101AB +:100A0000809100010E94D10F68E87BE28DED99E1B1 +:100A10000E942B2064E087E00E94870F68E088E155 +:100A20000E94870F63E082E10E94870F65E385E102 +:100A30000E94870F64E670E080E090E00E94321729 +:100A400083E30E94A10FCE0101960E94FD1F64E680 +:100A500070E080E090E00E943217CE0101960E9483 +:100A6000FD1F64E670E080E090E00E94321730C124 +:100A700066ED71E0CE0101960E94421BCE01019607 +:100A80000E942F118C01CE0101960E940B1B1016A3 +:100A900011060CF0C7C16FED71E0CE0101960E9406 +:100AA000421BCE0101960E942F118C01CE010196AE +:100AB0000E940B1B101611060CF00DC168EE71E0C0 +:100AC000CE014B960E94421BCE014B960E942F11E5 +:100AD0008C0166EA71E0CE0183960E94421BCE0132 +:100AE00083960E942F11AC014B5F5F4F98016EE817 +:100AF00075E0CE0101960E94571B4AE050E060E08D +:100B000070E089819A810E94672E6B017C01CE0181 +:100B100001960E940B1BCE0183960E940B1BCE01F7 +:100B20004B960E940B1B00919205109193056DE569 +:100B300073E0CE014B960E94421BCE014B960E9461 +:100B40002F11AC014B5F5F4F98016EE875E0CE014D +:100B500001960E94571B40E150E060E070E08981FF +:100B60009A810E94672E2B013C01CE0101960E94C2 +:100B70000B1BCE014B960E940B1BEBE3CE16E1E064 +:100B8000DE06E9F485E190E09093760580937505A3 +:100B90000E9438106FEF8FEF0E94D10F60EC74E865 +:100BA00086EC92E10E942B2064E087E00E94870F90 +:100BB00085E30E94A10F6DE080E00E94870F62E054 +:100BC00070E080E090E00E94321775E0A72EB12C13 +:100BD000E3E28E2EEAE09E2EF3E72F2EF4E03F2E86 +:100BE00061E084E10E94A11683EC94E10197F1F7A2 +:100BF00060E084E10E94A116C4010197F1F709E0C9 +:100C000010E061E084E10E94A116C4010197F1F7B0 +:100C100060E084E10E94A1168FE095E00197F1F772 +:100C20000150110971F70FE010E001501109D301D3 +:100C3000C201002E04C0B695A795979587950A9492 +:100C4000D2F761E080FF0CC084E10E94A116C401CC +:100C50000197F1F760E084E10E94A116C1010DC087 +:100C600084E10E94A1168BEB93E00197F1F760E01D +:100C700084E10E94A1168BEE9AE00197F1F701152D +:100C8000110599F6F1E0AF1AB10809F0A9CF6EEE9F +:100C900071E080E594E00E94F61562E072E080E584 +:100CA00094E00E94F615B701A601662777272AE08F +:100CB00080E594E00E94321568E072E080E594E0FF +:100CC0000E94F61540E150E0C301B2010E945E0FA0 +:100CD0000E948E20A1C721E130E04EE050E06EE896 +:100CE00075E0CE0101960E94571B4AE050E060E09B +:100CF00070E089819A810E94672E2B013C01CE0110 +:100D000001960E940B1B23E130E042E150E06EE8C7 +:100D100075E0CE0101960E94571B40E150E060E073 +:100D200070E089819A810E94672E6B017C018B01A2 +:100D3000CE0101960E940B1B2091920530919305E4 +:100D400044E150E06EE875E0CE0101960E94571B29 +:100D500040E150E060E070E089819A810E94672E56 +:100D60004B015C01CE0101960E940B1B2BE3421646 +:100D700021E052066104710419F40E946D2009C03B +:100D800031EB431631E053066104710411F40E9403 +:100D9000502068E0262E312CA801C501B4010E9424 +:100DA000A11F69E070E080E090E00E94321781E0CE +:100DB000281A310889F76FE072E080E594E00E941C +:100DC000F61562E072E080E594E00E94F6152AE0F4 +:100DD00030E0B301A20180E594E00E947B1564E459 +:100DE00072E080E594E00E94F615A601DD0C660B2A +:100DF000770B20E180E594E00E94321569E072E013 +:100E000080E594E00E94F61520E1B501A40180E59B +:100E100094E00E9432156AE172E080E594E00E945D +:100E20001D1556CF6DE172E0CE0101960E94421B66 +:100E3000CE0101960E942F118C01CE0101960E94D5 +:100E40000B1B101611060CF079C164E272E0CE01A2 +:100E500001960E94421BCE0101960E942F118C0127 +:100E600066EA71E0CE014B960E94421BCE014B9682 +:100E70000E942F11AC014B5F5F4F98016EE875E047 +:100E8000CE018F960E94571BCE014B960E940B1BE2 +:100E9000CE0101960E940B1B6BE272E0CE0101961F +:100EA0000E94421BCE0101960E942F118C0165E227 +:100EB00072E0CE014B960E94421BCE014B960E94DF +:100EC0002F11AC014A5F5F4F98016EE875E0CE01CB +:100ED00089960E94571BCE014B960E940B1BCE0198 +:100EE00001960E940B1B60E372E0CE0101960E9406 +:100EF000421BCE0101960E942F118C016CE272E020 +:100F0000CE014B960E94421BCE014B960E942F11A0 +:100F1000AC014C5F5F4F98016EE875E0CE0183969F +:100F20000E94571BCE014B960E940B1BCE010196CF +:100F30000E940B1B009192051091930561E372E0F2 +:100F4000CE0101960E94421BCE0101960E942F11F4 +:100F5000AC014B5F5F4F98016EE875E0CE014B9698 +:100F60000E94571BCE0101960E940B1B4AE050E0E5 +:100F700060E070E08FA598A90E94672E4B015C018C +:100F800040E150E060E070E089A59AA50E94672EDC +:100F90006B017C0140E150E060E070E08BA19CA11E +:100FA0000E94672E6DAB7EAB8FAB98AF40E150E0F7 +:100FB00060E070E08B8D9C8D0E94672E2B013C01C0 +:100FC0008B018DA99EA9AFA9B8AD0196A11DB11D38 +:100FD0008DAB9EABAFABB8AF9BE3891691E09906A2 +:100FE000A104B10419F40E946D2012C0A1EB8A166D +:100FF000A1E09A06A104B10419F40E94502008C08F +:101000002AE030E0B501A4018DEE94E00E947B154A +:1010100066E372E08DEE94E00E94F6152AE0B701D7 +:10102000A6018DEE94E00E9432156DE372E08DEE24 +:1010300094E00E94F6152AE04DA95EA96FA978AD4B +:101040008DEE94E00E94321563E472E08DEE94E040 +:101050000E94F6154AE050E0B2018DEE94E00E9445 +:10106000C915460157014DA85EA86FA878AC4C1869 +:101070005D086E087F088DA99EA9AFA9B8AD881636 +:101080009906AA06BB06D0F558E0252E312CA801FA +:10109000C501B4010E94A11F6CE070E080E090E007 +:1010A0000E943217B1E02B1A310889F760E570E031 +:1010B00080E090E00E943217EFEF8E1A9E0AAE0A8F +:1010C000BE0A6AE472E080E594E00E94F615A5018C +:1010D00094012C193D094E095F09A4E6B0E00E9475 +:1010E0009332A30192010E947432CA01B9014AE00D +:1010F00050E080E594E00E94C915BDCF80E594E002 +:101100000E94A7131816190634F40E948E2010921C +:101110002504109224040E948E20CE014B960E943A +:101120000B1BCE0183960E940B1BCE0189960E9459 +:101130000B1BCE018F960E940B1B6EC569E572E0FA +:10114000CE0101960E94421BCE0101960E942F11F2 +:101150008C01CE0101960E940B1B101611060CF09B +:1011600055C08091920590919305892B81F0009153 +:101170008E0510918F056DE070E0C8010E94C334A8 +:10118000009729F0DC01A01BB10B8D0102C00FEF0D +:101190001FEF60E672E0CE014B960E94421BCE012B +:1011A0004B960E942F11AC01495F5F4F98016EE88A +:1011B00075E0CE0101960E94571B61E772E0CE01F7 +:1011C00001960E94331A882359F060E088E00E945B +:1011D000A11667E672E080E594E00E94E21524C360 +:1011E0006FE772E0CE0101960E94331A882309F45A +:1011F0001BC361E088E00E94A11665E772E080E50C +:1012000094E00E94E2150E948E200EC362E872E014 +:10121000CE0101960E94421BCE0101960E942F1121 +:101220008C01CE0101960E940B1B101611060CF0CA +:10123000F3C468E872E0CE0101960E94421BCE0121 +:1012400001960E942F118C01CE0101960E940B1B6A +:10125000101611060CF0BBC065EA71E0CE010196D4 +:101260000E94421BCE0101960E942F118C016BEA55 +:1012700071E0CE014B960E94421BCE014B960E941C +:101280002F11AC014A5F5F4F98016EE875E0CE0107 +:1012900083960E94571BCE014B960E940B1BCE01DA +:1012A00001960E940B1B009192051091930566EA2E +:1012B00071E0CE014B960E94421BCE014B960E94DC +:1012C0002F11AC014B5F5F4F98016EE875E0CE01C6 +:1012D00001960E94571B4AE050E060E070E089816F +:1012E0009A810E94672E6093060170930701809394 +:1012F000080190930901CE0101960E940B1BCE01BB +:101300004B960E940B1B6BE972E0CE0183960E9404 +:10131000331A882331F101E010E010930B010093A0 +:101320000A01E99881E994E190930F0180930E01FD +:1013300086E30E94A10F60910601709107018091E0 +:101340000801909109010E942B2084E30E94A10FC3 +:101350001093800500937F050E9414116FE872E0DE +:101360002FC061EA72E0CE0183960E94331A88236F +:1013700059F182E090E090930B0180930A01E99883 +:1013800081E994E190930F0180930E0186E30E941E +:10139000A10F609106017091070180910801909161 +:1013A00009010E942B2084E30E94A10F81E090E0BC +:1013B00090936B0580936A050E94430F68EA72E080 +:1013C00080E594E00E94E215CE018396B4CE6BEBEB +:1013D00072E0CE0101960E94421BCE010196ABCE77 +:1013E00024E030E041E050E06EE875E0CE01019687 +:1013F0000E94571B64EC72E0CE0101960E94331AE2 +:10140000182FCE0101960E940B1B112309F4EDC386 +:1014100020E130E046E050E06EE875E0CE01019654 +:101420000E94571B68EC72E0CE0101960E94331AAD +:10143000182FCE0101960E940B1B112309F48CC0BA +:1014400081E090E0909333048093320468EE71E081 +:10145000CE014B960E94421BCE014B960E942F114B +:101460008C0163ED72E0CE0183960E94421BCE0197 +:1014700083960E942F11AC014D5F5F4F98016EE87B +:1014800075E0CE0101960E94571B89819A810E94C6 +:10149000792F90933D0480933C04CE0101960E94E5 +:1014A0000B1BCE0183960E940B1BCE014B960E9414 +:1014B0000B1B009192051091930569EE71E0CE012E +:1014C0004B960E94421BCE014B960E942F11AC01FD +:1014D0004B5F5F4F98016EE875E0CE0101960E9468 +:1014E000571B4AE050E060E070E089819A810E94D9 +:1014F000672E60933E0470933F0480934004909362 +:101500004104CE0101960E940B1BCE014B960E9416 +:101510000B1B60E073E080E594E00E94F6154091BB +:101520003C0450913D04052E000C660B770B2AE01D +:1015300030E080E594E00E947B156DEE72E080E57E +:1015400094E00E94F61560913E0470913F048091F2 +:1015500040049091410401C12CE030E046E050E0AD +:101560006EE875E0CE0101960E94571B66ED72E0B1 +:10157000CE0101960E94331A182FCE0101960E94C7 +:101580000B1B112309F4EEC082E090E0909333042A +:101590008093320464E272E0CE014B960E94421BBB +:1015A000CE014B960E942F118C0163ED72E0CE01AB +:1015B00083960E94421BCE0183960E942F11AC019C +:1015C0004D5F5F4F98016EE875E0CE0101960E9475 +:1015D000571B89819A810E94792F90933D048093B3 +:1015E0003C04CE0101960E940B1BCE0183960E9403 +:1015F0000B1BCE014B960E940B1B6BE272E0CE01DF +:101600004B960E94421BCE014B960E942F118C01DB +:1016100065E272E0CE0183960E94421BCE01839662 +:101620000E942F11AC014A5F5F4F98016EE875E090 +:10163000CE0101960E94571B4AE050E060E070E046 +:1016400089819A810E94672E6093340470933504D7 +:101650008093360490933704CE0101960E940B1BB1 +:10166000CE0183960E940B1BCE014B960E940B1B52 +:1016700000919205109193056CE272E0CE014B96B9 +:101680000E94421BCE014B960E942F11AC014C5F71 +:101690005F4F98016EE875E0CE0101960E94571BDE +:1016A0004AE050E060E070E089819A810E94672EF4 +:1016B000609338047093390480933A0490933B0408 +:1016C000CE0101960E940B1BCE014B960E940B1B74 +:1016D0008091340490913504A0913604B091370480 +:1016E00080933E0490933F04A0934004B093410440 +:1016F00060E073E080E594E00E94F61540913C04C0 +:1017000050913D04052E000C660B770B2AE030E06B +:1017100080E594E00E947B156DED72E080E594E039 +:101720000E94F615409134045091350460913604BE +:10173000709137042AE080E594E00E94321568EE4B +:1017400072E080E594E00E94F61560913804709193 +:10175000390480913A0490913B044AE050E00E94A1 +:101760005E0F5AC22CE030E046E050E06EE875E0D3 +:10177000CE0101960E94571B61EF72E0CE010196E7 +:101780000E94331A182FCE0101960E940B1B1123C1 +:1017900009F451C08091920590919305892B81F0B5 +:1017A00000918E0510918F056DE070E0C8010E94D8 +:1017B000C334009729F0FC01E01BF10B8F0102C03C +:1017C0000FEF1FEF60E672E0CE014B960E94421BC6 +:1017D000CE014B960E942F11AC01495F5F4F9801DB +:1017E0006EE875E0CE0101960E94571B61E772E03A +:1017F000CE0101960E94331A882331F061E086E021 +:101800000E94A11661E00DC06FE772E0CE01019663 +:101810000E94331A882341F060E086E00E94A116FE +:1018200060E089E00E94A116CE0101960E940B1B88 +:10183000CE014B9680CC68EF72E0CE0101960E94FB +:10184000421BCE0101960E942F118C01CE01019600 +:101850000E940B1B101611060CF0DEC168EE71E041 +:10186000CE014B960E94421BCE014B960E942F1137 +:101870008C0163ED72E0CE0183960E94421BCE0183 +:1018800083960E942F11AC014D5F5F4F98016EE867 +:1018900075E0CE0101960E94571B89819A810E94B2 +:1018A000792F90933D0480933C04CE0101960E94D1 +:1018B0000B1BCE0183960E940B1BCE014B960E9400 +:1018C0000B1B009192051091930569EE71E0CE011A +:1018D0004B960E94421BCE014B960E942F11AC01E9 +:1018E0004B5F5F4F98016EE875E0CE0101960E9454 +:1018F000571B4AE050E060E070E089819A810E94C5 +:10190000672E60933E0470933F048093400490934D +:101910004104CE0101960E940B1BCE014B960E9402 +:101920000B1B6EEF72E080E594E00E94F61540918B +:101930003C0450913D04052E000C660B770B2AE009 +:1019400030E080E594E00E947B156DEE72E080E56A +:1019500094E00E94F61560913E0470913F048091DE +:101960004004909141044AE050E00E945E0FC09014 +:101970003E04D0903F04E0904004F0904104009178 +:101980003C0410913D0488E0E3E3F1E0DE015B9666 +:1019900001900D928A95E1F71FA618AA19AA1AAA12 +:1019A00080E490E8A4E1B0E089A79AA7ABA7BCA720 +:1019B00060E089E00E94A11664E270E080E090E0BF +:1019C0000E94321740E062E0CE014B960E94840EE6 +:1019D00060E170E080E090E00E94321747E061E053 +:1019E000CE018F960E94840E61E270E080E090E06C +:1019F0000E94321740E061E0CE0189960E94840E79 +:101A000060E170E080E090E00E943217C801807FC2 +:101A1000992724E0959587952A95E1F79A838983FC +:101A20000F7011271C830B83FE01359620E030E0F8 +:101A30004FE0842E912CA12CB12CA901445E5F4F64 +:101A4000D501C401042E04C0880F991FAA1FBB1F13 +:101A50000A94D2F78C219D21AE21BF2104C0B695F6 +:101A6000A795979587954A95D2F78193919324509E +:101A70003109203E8FEF380701F7CE0101960E9411 +:101A80006F113C01812C912CB0E0A0E01DAA19AE91 +:101A9000212C512C80E8382E44244A94F301808173 +:101AA0003181F2E06F0E711C282F932F990F990B43 +:101AB000740182E3E80EF11C492F592F692F792F09 +:101AC000892F0E2D0E949F3359016A017B018C01E1 +:101AD0002B2F3A2F4DA959AD622D752D832D942DA5 +:101AE0000E94D633B22FA32F4DAB59AF262E572EBF +:101AF000382E492E95E0891A9108E9EC8E16EFEF01 +:101B00009E0661F62B2F3A2F622D752D832D942D75 +:101B100000E20E94BA332BA33CA34DA35EA39D0118 +:101B20009DA989AD39832A839B838C8341E061E041 +:101B3000CE0183960E94840E60E170E080E090E028 +:101B40000E94321742E061E0CE0101960E94840EAD +:101B500060E170E080E090E00E94321761E089E08F +:101B60000E94A11665E870E080E090E00E943217C4 +:101B700060E089E00E94A11665E870E080E090E0F6 +:101B80000E94321761E089E00E94A11661E086E0C0 +:101B90000E94A11664E670E080E090E00E94321797 +:101BA00060E089E00E94A11660E086E00E94A11634 +:101BB00064E670E080E090E00E94321761E089E026 +:101BC0000E94A11661E086E00E94A11664E670E022 +:101BD00080E090E00E94321760E089E00E94A11648 +:101BE00060E086E00E94A11617C064E073E080E523 +:101BF00094E00E94F61560E070E08EE895E00E94A7 +:101C0000211ADC016C91062E000C770B40E150E0AC +:101C100080E594E00E94C9156CE172E08EE895E0E1 +:101C20000E94BB1AE9960FB6F894DEBF0FBECDBF77 +:101C3000DF91CF911F910F91FF90EF90DF90CF90A8 +:101C4000BF90AF909F908F907F906F905F904F90DC +:101C50003F902F900895CF93C62FBC018DEE94E056 +:101C60000E94F6156BE073E08DEE94E00E94F6158D +:101C70008C2F0E94BB12482F50E060E070E020E102 +:101C80008DEE94E00E9432156AE172E08DEE94E0F0 +:101C90000E941D15CF91089560E086E00E94A11674 +:101CA0008BE891E00197F1F761E086E00E94A116D0 +:101CB00083E592E00197F1F760E086E00C94A116CD +:101CC00060E086E00E94A11683E795E00197F1F7B6 +:101CD00061E086E00E94A11683E592E00197F1F7AA +:101CE00060E086E00C94A1160E94B534E6E5F5E0CC +:101CF00016821782108611861286138614826AE570 +:101D000075E0CF010C946E27CF92DF92FF920F9374 +:101D10001F93CF93DF936C01C62FF42E61E086E012 +:101D20000E94A1168BEB93E00197F1F760E086E04B +:101D30000E94A1160E94600E0E944C0E0E944C0E42 +:101D4000CC23F1F00FE110E0F60180819181A281B6 +:101D5000B381002E04C0B695A795979587950A94F0 +:101D6000D2F780FF03C00E94600E02C00E944C0E9A +:101D70000150110948F724E0C20ED11CC150E0CF38 +:101D8000C2E0D0E00F2D10E0C8010C2E02C09595E6 +:101D900087950A94E2F780FF03C00E94600E02C09C +:101DA0000E944C0E219780F7DF91CF911F910F91E8 +:101DB000FF90DF90CF900895FC018091490481113C +:101DC00003C08FEF9FEF08959FB7F89482E0809350 +:101DD000E9002091F20030E01216130614F421E01D +:101DE00030E02115310559F0289A84E680934804A3 +:101DF0008091F10080838091F200882319F09FBFC9 +:101E0000C90108958BE68093E800F9CFE82FF0E050 +:101E1000EE0FFF1FE45FFE4F718360838230D9F0C5 +:101E200028F4882341F0813071F008958330D9F08F +:101E3000843009F10895809169008C7F81608093DE +:101E40006900E89A089580916900837F8460809397 +:101E50006900E99A0895809169008F7C8061809380 +:101E60006900EA9A0895809169008F738064809375 +:101E70006900EB9A089580916A008F7C806180935D +:101E80006A00EE9A089580916A0590916B058F3FE4 +:101E90002FEF920791F01092620510926305109255 +:101EA0006405109265051092A7051092A60585306D +:101EB00020F46CEF75E20C94060F0895CF93DF9336 +:101EC0004115510559F4E0915004F09151040190ED +:101ED000F081E02D80E594E0099507C0242FAB0147 +:101EE000BC0180E594E00E943215EC016AE172E0E9 +:101EF00080E594E00E941D158C0F9D1FDF91CF910E +:101F000008958EBD0DB407FEFDCF8EB508950F93D5 +:101F10001F93CF93DF93082F162FC3E7D5E060E020 +:101F20008A810E94A116802F0E94810F812F0E941A +:101F3000810F61E08A81DF91CF911F910F910C9405 +:101F4000A1161F93CF93DF93182FC3E7D5E060E06E +:101F50008A810E94A116812F0E94810F61E08A81EF +:101F6000DF91CF911F910C94A1161F93CF93DF9314 +:101F700060E0809175050E94A1168EE70E94810F96 +:101F8000CBE3D1E01C2F185F89910E94810F1C13B5 +:101F9000FBCF61E080917505DF91CF911F910C948B +:101FA000A116CF93DF9390917C05981304C0909174 +:101FB0007D05961771F0C62FD82F682F84E00E94F8 +:101FC000870F6C2F85E00E94870FD0937C05C0930C +:101FD0007D05DF91CF910895CF93DF93C3E7D5E0DF +:101FE00061E08A810E94A1168FE090E00197F1F7ED +:101FF00060E08A810E94A11683E290E00197F1F7E8 +:1020000061E08A810E94A1168FE990E00197F1F7C3 +:1020100060E08A810E94A1166AE070E080E090E0B2 +:102020000E94321780E30E94810F6AE070E080E036 +:1020300090E00E94321761E08A81DF91CF910C9489 +:10204000A11661E080E10E94D11660E08EE00E945E +:10205000D11661E08FE00E94D11661E08FE00E940E +:10206000A11660E080E10E94A11680E58CBD089574 +:1020700061E0809175050E94D1160E94211060E0F8 +:1020800082E00E94D11664E070E080E090E00E945F +:1020900032170E94EC0F69E280E00E94870F6EE227 +:1020A00081E00E94870F66E082E00E94870F67E46C +:1020B00083E00E94870F6FEF86E00E94870F60E049 +:1020C00087E00E94870F60E388E00E94870F61E944 +:1020D00083ED0E94D10F80917E05882331F060E06E +:1020E00089E00E94870F10927E0580917B058823EE +:1020F00031F060E08AE00E94870F10927B0566E075 +:102100008BE00E94870F60E08CE00E94870F60E107 +:102110008DE00E94870F60EB8EE00E94870F61E7E1 +:102120008FE00E94870F82E080937A0568EF80E15C +:102130000E94870F63E981E10E94870F63E382E1D8 +:102140000E94870F62E283E10E94870F68EF84E1BB +:102150000E94870F60E085E10E94870F67E086E1BB +:102160000E94870F60E287E10E94870F68E188E1A3 +:102170000E94870F66E189E10E94870F6CE68AE181 +:102180000E94870F60E08BE10E94870F60E48CE182 +:102190000E94870F61E98DE10E94870F67E88EE159 +:1021A0000E94870F6BE68FE10E94870F6BEF80E242 +:1021B0000E94870F66E581E20E94870F61E182E25B +:1021C0000E94870F69EE83E20E94870F6AE284E231 +:1021D0000E94870F60E085E20E94870F6FE186E230 +:1021E0000E94870F61E487E20E94870F60E088E227 +:1021F0000E94870F69E589E20E94870F6FE78AE2F4 +:102200000E94870F6FE38BE20E94870F61E88CE2E8 +:102210000E94870F65E38DE20E94870F6BE08EE2DC +:102220000E94870F0C94B50F80917F0590918005D7 +:102230008F3F2FEF920791F010926605109267057D +:10224000109268051092690510924F0410924E0486 +:10225000853020F463E973E20C94060F0895CF9360 +:10226000DF932091920530919305232B79F0FC01A7 +:10227000C0918E05D0918F0560817181CE010E9441 +:10228000DE34009719F08C1B9D0B02C08FEF9FEF7F +:10229000DF91CF910895CF93DF93EBE1F1E084914B +:1022A000ECEFF0E0D491EDEDF0E0C491CC2391F0AF +:1022B00081110E946416EC2FF0E0EE0FFF1FE65331 +:1022C000FF4FA591B491EC91ED2381E090E021F4D2 +:1022D00080E002C080E090E0DF91CF9108950F93FD +:1022E0001F93CF93DF93BC016C5E7F4FFC01408155 +:1022F0005181DA0120E030E0109729F02A273B27AE +:10230000B695A795F9CF440F551F21703327240F99 +:10231000351F21933193E617F70749F7E4E0F0E022 +:10232000A1E0B0E08D010E2E02C0000F111F0A9433 +:10233000E2F7EC0120E030E049915991402351232C +:102340000E2E02C0559547950A94E2F724273527AB +:10235000C617D70789F73197217033270E2E02C091 +:10236000220F331F0A94E2F740914C0450914D0420 +:10237000240F351F30934D0420934C04309791F671 +:10238000220F331FFC01358B248B10924D041092C9 +:102390004C04DF91CF911F910F9108952F923F929E +:1023A0004F925F926F927F928F929F92AF92BF9265 +:1023B000CF92DF92EF92FF920F931F93CF93DF9311 +:1023C000CDB7DEB76B970FB6F894DEBF0FBECDBFAB +:1023D0009C01207F3327E4E035952795EA95E1F7C6 +:1023E0003A8329838F7099279C838B83FE013596CE +:1023F00020E030E0AFE0CA2ED12CE12CF12C890195 +:10240000045E1F4FD701C601002E04C0880F991F1C +:10241000AA1FBB1F0A94D2F784239523A623B723B0 +:1024200004C0B695A795979587950A95D2F781939D +:10243000919324503109203E8FEF380701F7CE01E8 +:1024400001960E946F11DC01E0E0F0E0D12CE12C5C +:10245000F12C212C312C412C20E8C22E8FEF8B8FB8 +:102460008C9111963C9111971296282F932F990FCA +:10247000990B8F010E5C1F4F492F592F692F792F10 +:10248000892F0E949F3359013A014B018C012D2D58 +:102490003E2D4F2D522D632D742D8C2D9B8D630160 +:1024A00074010E94D633522E132FB42EA52E962ED1 +:1024B000872E782E692ED22EE32EF42E252E362E40 +:1024C000472EC82E9B8F3597E93C8FEFF80741F6D2 +:1024D00080E4E82EF12C93EEC92E93E0D92E81E012 +:1024E000E81AF108252D312F4B2D5A2D692D782D05 +:1024F000872D962D0E2D0E94BA33217030E040E0DA +:1025000050E060E070E080E090E0A0E00E94DF3307 +:1025100041F086E00E94A116C6010197F1F761E043 +:1025200008C061E086E00E94A116C6010197F1F79C +:1025300060E086E00E94A116C6010197F1F7E11460 +:10254000F10469F66B960FB6F894DEBF0FBECDBFEF +:10255000DF91CF911F910F91FF90EF90DF90CF907F +:10256000BF90AF909F908F907F906F905F904F90B3 +:102570003F902F9008951F93CF93DF93182FC3E7B9 +:10258000D5E060E08A810E94A116812F806C0E94B4 +:10259000810F80E00E94810F182F61E08A810E94E4 +:1025A000A116812FDF91CF911F9108957F928F9275 +:1025B0009F92AF92BF92CF92DF92EF92FF920F93D2 +:1025C0001F93CF93DF93CDB7DEB7762E6A018DB61A +:1025D0009EB62DB73EB7241B350B0FB6F8943EBF01 +:1025E0000FBE2DBFEDB7FEB731967F01BC018DEE5A +:1025F00094E00E94F6156BE073E08DEE94E00E948B +:10260000F615570100E010E0872D800F0C151D0511 +:10261000B9F00E94BB12F50181935F01482F50E091 +:1026200060E070E020E18DEE94E00E9432156EE0F3 +:1026300073E08DEE94E00E94F6150F5F1F4FE4CF1C +:102640006CE172E08DEE94E00E94E215C7010FB6D6 +:10265000F8949EBE0FBE8DBEDF91CF911F910F915A +:10266000FF90EF90DF90CF90BF90AF909F908F90B2 +:102670007F9008952FB7F89487708093E900909128 +:10268000E800892F807295FF04C09091F20080E4E9 +:10269000891B2FBF0895CF92DF92EF92FF920F9385 +:1026A0001F93CF93DF936C017A018B01C0E0D0E0E0 +:1026B000CE15DF0589F0D8016D918D01D601ED9120 +:1026C000FC910190F081E02DC6010995892B11F450 +:1026D0007E0102C02196ECCFC701DF91CF911F91FF +:1026E0000F91FF90EF90DF90CF900895FC01538DF4 +:1026F000448D252F30E0842F90E0821B930B5417DC +:1027000010F0CF96089501970895FC01918D828D68 +:10271000981761F0828DDF01A80FB11D5D968C9135 +:10272000928D9F5F9F73928F90E008958FEF9FEF40 +:102730000895FC01918D828D981731F0828DE80FFC +:10274000F11D858D90E008958FEF9FEF0895FC01B6 +:10275000918D228D892F90E0805C9F4F821B910983 +:102760008F739927089580E594E00E94A71321E0D4 +:10277000892B09F420E0822F0895FC01848DDF016C +:10278000A80FB11DA35ABF4F2C91848D90E00196E4 +:102790008F739927848FA689B7892C93A089B189D3 +:1027A0008C9180648C93938D848D981306C00288DD +:1027B000F389E02D80818F7D80830895EF92FF92D1 +:1027C0000F931F93CF93DF93EC0181E0888F9B8D54 +:1027D0008C8D981305C0E889F989808185FD24C016 +:1027E000F62E0B8D10E00F5F1F4F0F731127E02E99 +:1027F0008C8DE8120CC00FB607FCFACFE889F98976 +:10280000808185FFF5CFCE010E94BD13F1CF8B8D66 +:10281000FE01E80FF11DE35AFF4FF0820B8FEA89AA +:10282000FB898081806207C0EE89FF896083E88927 +:10283000F98980818064808381E090E0DF91CF918D +:102840001F910F91FF90EF900895CF93DF93EC01CC +:10285000888D8823C9F0EA89FB89808185FD05C0C0 +:10286000A889B9898C9186FD0FC00FB607FCF5CFFA +:10287000808185FFF2CFA889B9898C9185FFEDCF42 +:10288000CE010E94BD13E7CFDF91CF91089580E084 +:1028900090E0892B29F00E94B31381110C94000061 +:1028A0000895CF93DF931F92CDB7DEB76983DC0124 +:1028B000ED91FC910280F381E02D41E050E0BE01FA +:1028C0006F5F7F4F09950F90DF91CF91089583E05F +:1028D0008093E9008091F200882319F08AE38093C5 +:1028E000E800089583E00E943A1390E00895FC0107 +:1028F0008485958597FD0BC09FB7F89482E08093FF +:10290000E9008091F2009FBF90E0019608959FB783 +:10291000F89482E08093E9008091F2009FBF90E0FC +:10292000089508950F931F93CF93DF931F92CDB710 +:10293000DEB78C01FC018485958597FF0EC0CE0122 +:1029400001960E94DC0E019719F4298130E002C043 +:102950002FEF3FEFF80135872487F80184859585AF +:102960000F90DF91CF911F910F910895CF93DF9337 +:102970001F92CDB7DEB7FC018485958597FD05C014 +:102980002FEF3FEF358724870BC0CE0101960E94C1 +:10299000DC0E019719F4898190E002C08FEF9FEF60 +:1029A0000F90DF91CF9108954091EB055091EC0588 +:1029B0002091E9053091EA0542175307B4F490914C +:1029C000E8009570E1F39091E80092FD19C08093C2 +:1029D000F1008091EB059091EC0501968F7399279A +:1029E000892B19F48EEF8093E8008091EB0590918C +:1029F000EC0501969093EC058093EB0581E008953A +:102A000080E00895615030F02091F100FC012083B6 +:102A10000196F8CF289A84E6809348040895DC0153 +:102A2000ED91FC91DB0114964D915C9115976D91A0 +:102A30007C910280F381E02D09946115710579F094 +:102A4000FB0101900020E9F73197AF01461B570BBE +:102A5000DC01ED91FC910280F381E02D099480E08E +:102A600090E008954F925F926F927F92EF92FF9263 +:102A70000F931F93CF93DF93CDB7DEB7A1970FB618 +:102A8000F894DEBF0FBECDBF7C01FA01CB0119A2C5 +:102A9000223008F42AE08E010F5D1F4F422E512C88 +:102AA000612C712CBF01A30192010E945232F901E5 +:102AB000CA01015011096A3014F4605D01C0695CFB +:102AC000D8016C93232B242B252B61F7B801C70168 +:102AD0000E941D15A1960FB6F894DEBF0FBECDBFA4 +:102AE000DF91CF911F910F91FF90EF907F906F90AA +:102AF0005F904F900895CF92DF92EF92FF920F93E5 +:102B00001F93CF93DF93EC016A017B0121153105FF +:102B100079F4E881F9810190F081E02D642FDF9153 +:102B2000CF911F910F91FF90EF90DF90CF9009947C +:102B30002A30310509F577FF1EC0E881F98101903F +:102B4000F081E02D6DE209958C0144275527BA01EB +:102B50004C195D096E097F092AE0CE010E943215E9 +:102B6000800F911FDF91CF911F910F91FF90EF90F8 +:102B7000DF90CF9008952AE0B701A601CE01DF9142 +:102B8000CF911F910F91FF90EF90DF90CF900C9419 +:102B900032150F931F93CF93DF93EC019A01AB0192 +:102BA000770F660B770B0E947B158C016AE172E050 +:102BB000CE010E941D15800F911FDF91CF911F91B3 +:102BC0000F9108950F931F93CF93DF93EC010E9411 +:102BD0001D158C016AE172E0CE010E941D15800F67 +:102BE000911FDF91CF911F910F9108950C941D15A6 +:102BF0008091E10581110DC082E08093DD0584E0C4 +:102C00008093DE051092E0051092DF0581E080934D +:102C1000E1058DED95E008951F920F920FB60F928A +:102C200011242F933F934F935F936F937F938F93D1 +:102C30009F93AF93BF93EF93FF9380E594E00E943F +:102C4000BD13FF91EF91BF91AF919F918F917F91B4 +:102C50006F915F914F913F912F910F900FBE0F9009 +:102C60001F9018951F920F920FB60F9211242F9359 +:102C70008F939F93EF93FF93E0916004F091610431 +:102C80008081E0916604F091670482FD12C090811A +:102C9000809169048F5F8F7320916A04821751F0CD +:102CA000E0916904F0E0E05BFB4F958F809369044D +:102CB00001C08081FF91EF919F918F912F910F9093 +:102CC0000FBE0F901F90189590E0FC013197EF30E8 +:102CD000F105B0F5EA5AFF4F0C94993380918000CA +:102CE0008F7703C0809180008F7D8093800008954E +:102CF00080918000877FF9CF84B58F7702C084B53B +:102D00008F7D84BD0895809190008F7707C080915A +:102D100090008F7D03C080919000877F809390000A +:102D200008958091C0008F7703C08091C0008F7D8F +:102D30008093C00008958091C200877F8093C20075 +:102D400008951F93CF93DF93282F30E0F901EA5EB7 +:102D5000FE4F8491F901E950FF4FD491F901E852F7 +:102D6000FF4FC491CC23C9F0162F81110E94641625 +:102D7000EC2FF0E0EE0FFF1FEF54FE4FA591B49142 +:102D80008FB7F894111105C09C91ED2FE095E923C0 +:102D900002C0EC91ED2BEC938FBFDF91CF911F918F +:102DA0000895CF93DF9390E0FC01E950FF4F249109 +:102DB000FC01E852FF4F8491882361F190E0880F75 +:102DC000991FFC01ED55FE4FC591D491FC01EF54C4 +:102DD000FE4FA591B491611109C09FB7F894888105 +:102DE000209582238883EC912E230BC0623061F4FE +:102DF0009FB7F8943881822F809583238883EC9144 +:102E00002E2B2C939FBF06C08FB7F894E8812E2BF2 +:102E100028838FBFDF91CF9108953FB7F8948091B9 +:102E2000D9059091DA05A091DB05B091DC0526B5B6 +:102E3000A89B05C02F3F19F00196A11DB11D3FBFF2 +:102E4000BA2FA92F982F8827820F911DA11DB11D80 +:102E5000BC01CD0142E0660F771F881F991F4A957C +:102E6000D1F708958F929F92AF92BF92CF92DF9247 +:102E7000EF92FF926B017C010E940D174B015C01E8 +:102E8000C114D104E104F104F1F00E940D17DC013A +:102E9000CB0188199909AA09BB09883E9340A1056D +:102EA000B10570F321E0C21AD108E108F10888EEFB +:102EB000880E83E0981EA11CB11CC114D104E1044A +:102EC000F10419F7DDCFFF90EF90DF90CF90BF9026 +:102ED000AF909F908F9008957F928F929F92AF9224 +:102EE000BF92CF92DF92EF92FF920F931F93CF93F7 +:102EF000DF93C82E8B017A0180914904811103C0B0 +:102F00008FEF9FEF75C08091300480FF05C08091E6 +:102F1000E00082608093E000CE2DDF2DD12C8AEF7F +:102F2000882E8C2D8770B82E8C2D8072A82E8C2D1B +:102F30008074982E9AE3792E209709F452C08C2D34 +:102F40000E943A13282F81110AC08A948820C1F266 +:102F500061E070E080E090E00E943217EDCF90E0F9 +:102F6000C817D9070CF42C2F3FB7F894B092E9009A +:102F70008091E80085FF33C0822F90E0C81BD90BF9 +:102F8000AA2029F02150A8F01092F100FBCFF801FF +:102F9000C7FE07C0215058F044914093F10031968C +:102FA000F9CF215020F041914093F100FACF080F62 +:102FB000191FDD2019F07092E8000AC08091E80026 +:102FC00085FD08C07092E800DD24D394209739F085 +:102FD000D12C05C0209719F491107092E8003FBFE2 +:102FE000ABCFD110ACCF5D9A84E68093ED05C701DD +:102FF000DF91CF911F910F91FF90EF90DF90CF90D5 +:10300000BF90AF909F908F907F900895CF93DF9364 +:10301000EC0180912C01882331F083E00E946C1731 +:103020001816190634F081E090E09B838A8380E0D3 +:1030300090E0DF91CF9108952FB7F8946091D50576 +:103040007091D6058091D7059091D8052FBF08952E +:103050001F920F920FB60F9211242F933F938F93CD +:103060009F93AF93BF938091D5059091D605A09182 +:10307000D705B091D8053091D40523E0230F2D3723 +:1030800020F40196A11DB11D05C026E8230F02966C +:10309000A11DB11D2093D4058093D5059093D6052D +:1030A000A093D705B093D8058091D9059091DA0502 +:1030B000A091DB05B091DC050196A11DB11D8093A7 +:1030C000D9059093DA05A093DB05B093DC05BF9199 +:1030D000AF919F918F913F912F910F900FBE0F90C5 +:1030E0001F9018951F920F920FB60F9211242F93D5 +:1030F0003F934F935F936F937F938F939F93AF9380 +:10310000BF93EF93FF93E0911401F091150109959E +:10311000FF91EF91BF91AF919F918F917F916F91AF +:103120005F914F913F912F910F900FBE0F901F9085 +:1031300018951F920F920FB60F9211242F933F9361 +:103140004F935F936F937F938F939F93AF93BF93AF +:10315000EF93FF93E0911201F09113010995FF9114 +:10316000EF91BF91AF919F918F917F916F915F91FF +:103170004F913F912F910F900FBE0F901F90189578 +:103180001F920F920FB60F9211242F933F934F93DC +:103190005F936F937F938F939F93AF93BF93EF93BF +:1031A000FF93E0911001F09111010995FF91EF91CA +:1031B000BF91AF919F918F917F916F915F914F914F +:1031C0003F912F910F900FBE0F901F9018951F9257 +:1031D0000F920FB60F9211242F933F934F935F934B +:1031E0006F937F938F939F93AF93BF93EF93FF93CF +:1031F000E0910E01F0910F010995FF91EF91BF91C0 +:10320000AF919F918F917F916F915F914F913F917E +:103210002F910F900FBE0F901F9018951F920F9235 +:103220000FB60F9211242F933F934F935F936F9399 +:103230007F938F939F93AF93BF93EF93FF93E0910F +:103240000C01F0910D010995FF91EF91BF91AF91A4 +:103250009F918F917F916F915F914F913F912F91AE +:103260000F900FBE0F901F901895CF93DF93EC0136 +:1032700081E08C838D839E01265F3F4F3F832E83A9 +:103280001986188627E731E0398328831C861B8638 +:103290001E861D868F87888B81EC8A870E94F81591 +:1032A000FC0121818C8190E0820F911D089774F5BB +:1032B000A281B381109719F4D383C2830CC01896EE +:1032C0008D919C911997009711F0DC01F8CF199618 +:1032D000DC93CE93189780818A8381818B83908140 +:1032E0008D81890F808380E09C81891778F4AE817D +:1032F000BF81A80FB11D9C91A181B0E0A65EBE4F19 +:103300009C9391819F5F91838F5FEECFDF91CF91EF +:1033100008950895CF93DF93EC01888199810097F8 +:1033200011F00E949C30198218821D821C821B821F +:103330001A82DF91CF9108950F931F93CF93DF935C +:10334000EC0188819981009729F02A813B81261719 +:10335000370788F48B016F5F7F4F0E94EB33009734 +:1033600061F0998388831B830A832C813D81232B01 +:1033700011F4FC01108281E001C080E0DF91CF9167 +:103380001F910F910895EF92FF920F931F93CF9388 +:10339000DF93EC017B018A01BA010E949C19811123 +:1033A00004C0CE010E948A1907C01D830C83B70197 +:1033B000888199810E94D734CE01DF91CF911F91EE +:1033C0000F91FF90EF900895CF92DF92EF92FF92CE +:1033D0000F931F93CF93DF931F92CDB7DEB7182FB4 +:1033E000062FE42E862F880F8E5F99830E94D414B7 +:1033F00083E00E94D414F12EC12E9981D92E8C2DF8 +:103400008F19801798F4F601E7FE02C0849101C07D +:1034100080810E94D414182F80E00E94D41481234C +:10342000FFEFCF1ADF0A8111EACF01C081E00F90D0 +:10343000DF91CF911F910F91FF90EF90DF90CF9090 +:103440000895FC01248135816217730720F480817F +:103450009181009729F41092EE058EEE95E0089583 +:10346000860F971F0895FC0124813581232B31F4A9 +:1034700021E061157105A1F0FB0108C0FC0180810C +:1034800091816115710531F421E0FC01808188236F +:1034900039F005C00E94CE3421E0892B09F020E0EC +:1034A000822F0895EF92FF920F931F93CF93DF9394 +:1034B000FC01248135816115710511F480E019C08A +:1034C00041155105A9F07B01EC018A01020F131F80 +:1034D000B8010E949C19882389F3288139818C8145 +:1034E0009D81B701820F931F0E94D7341D830C83E7 +:1034F00081E0DF91CF911F910F91FF90EF900895A0 +:10350000CF93DF93EC016115710561F0FB01019030 +:103510000020E9F73197AF01461B570B0E94521A62 +:10352000811103C0CE010E948A19CE01DF91CF9193 +:103530000895CF93DF93EC01FB01448155816081B5 +:1035400071810E94521A811103C0CE010E948A1912 +:10355000CE01DF91CF9108956115710551F0FB0106 +:1035600001900020E9F73197AF01461B570B0C94EF +:10357000521A80E00895CF93DF93EC016115710535 +:1035800059F0FB0101900020E9F73197AF01461B8C +:10359000570B0E94C31902C00E948A19CE01DF9105 +:1035A000CF9108950F931F93CF93DF938C01EB017D +:1035B000FC01808191810097B1F06881798161156A +:1035C000710579F0428153812C813D814217530767 +:1035D00040F00E94D7348C819D81F80195838483CB +:1035E00013C00E949C3088819981F8019183808367 +:1035F0008A819B81938382838C819D81958384833F +:10360000198218821B821A821D821C82DF91CF913F +:103610001F910F910895FC01808191810C949C3041 +:10362000CF93DF9300D0CDB7DEB7FC0111821082BB +:10363000138212821582148269831A82BE016F5F1F +:103640007F4F0E94BB1A0F900F90DF91CF9108958A +:10365000FB01DC0111961C921E9213961C921E9285 +:10366000129715961C921E9214978617970749F089 +:10367000608171816115710521F0448155810C943F +:10368000C3190895FC0111821082138212821582DF +:1036900014826115710551F0FB0101900020E9F7DA +:1036A0003197AF01461B570B0C94C3190895BF9275 +:1036B000CF92DF92EF92FF920F931F93CF93DF93FE +:1036C0007C016B018A01E9012417350720F4812F61 +:1036D0008901C42FD82F6CE172E0C7010E94421B00 +:1036E000D60114968D919C91159708171907D0F45F +:1036F0008C179D0708F4EC01D601ED91FC91119710 +:10370000EC0FFD1FB08010824D915C91BA01600FEB +:10371000711FC7010E94BB1AD601ED91FC91EC0FFD +:10372000FD1FB082C701DF91CF911F910F91FF90D4 +:10373000EF90DF90CF90BF9008951F920F920FB639 +:103740000F9211248F939F938091E1009091E1005B +:10375000937F9093E10083FF0FC01092E90091E006 +:103760009093EB001092EC0092E39093ED00109296 +:10377000490498E09093F00082FF20C093E090937A +:10378000E9009091F200992319F09AE39093E800F0 +:103790009091ED05992339F09091ED05915090931A +:1037A000ED05992389F190914804992339F090917E +:1037B0004804915090934804992341F184FF10C02C +:1037C0008091E2008E7E81608093E2008091E10032 +:1037D0008F7E8093E100809130048E7E806111C0E5 +:1037E00080FF16C08091E2008E7E80618093E200AF +:1037F0008091E1008E7E8093E100809130048E7E86 +:1038000081608093300404C05D98CDCF2898D6CFD6 +:103810009F918F910F900FBE0F901F901895DF9280 +:10382000EF92FF920F931F93CF93DF93D82E8A01CD +:103830007B01E40EF51EEB01CE15DF0571F0D7FE1E +:1038400003C0FE01849101C088810E94D414219696 +:103850008111F2CF8FEF9FEF01C0C801DF91CF91AF +:103860001F910F91FF90EF90DF9008950F931F939A +:10387000CF93DF931F92CDB7DEB782E0898342E416 +:1038800050E06FEB71E080E80E940F1C0E94F81579 +:10389000DC0112960D911C9113970115110569F029 +:1038A000D801ED91FC910280F381E02DBE016F5FA4 +:1038B0007F4FC801099597FF07C089810F90DF915D +:1038C000CF911F910F910895F80100851185E5CFE3 +:1038D0001F920F920FB60F921124CF92DF92EF92A8 +:1038E000FF920F931F932F933F934F935F936F9389 +:1038F0007F938F939F93AF93BF93EF93FF93CF9358 +:10390000DF93CDB7DEB76C97DEBFCDBF1092E90075 +:103910008091E80083FFEDC168E0CE0145960E94EA +:10392000021582EF8093E8008D8987FF05C0909192 +:10393000E80090FFFCCF03C09EEF9093E800982F23 +:10394000907609F0C6C09E892F89188D91110CC000 +:10395000803829F4809131048093F10002C01092E4 +:10396000F1001092F10048C1422F50E0512B9130EC +:1039700051F4811141C14130510509F03DC180919F +:1039800031048D7F0BC0933061F4811135C141301A +:10399000510509F031C18091310482608093310476 +:1039A0002BC1953041F48091E80080FFFCCF206866 +:1039B0002093E30021C1963009F05FC0EB8CFC8CB2 +:1039C0001092E9001092EC051092EB05123091F57F +:1039D0001092EA051092E9050E94361C99E0BE019A +:1039E0006F5F7F4FDB01E92F1D92EA95E9F799831D +:1039F0001A8391E09E8390EA98879AEF99872091A5 +:103A0000EB053091EC05275F3F4F3C832B838D8383 +:103A10001092E9001092EC051092EB05F092EA0585 +:103A2000E092E90549E050E080E00E940F1C0E940E +:103A3000361CE2C0F092EA05E092E9050E94F81512 +:103A4000DC011296ED90FC901397E114F10409F457 +:103A5000C0C0D701ED91FC910480F581E02DBE013D +:103A60006B5E7F4FC7010995009719F00CF0C4C039 +:103A7000C7C0F701E084F184E8CF973009F4C0C0F3 +:103A8000983021F481E08093F100B6C0993009F0BC +:103A9000B3C0837009F0B4C0EBE1F1E081E021E054 +:103AA00036E39081992361F08093E9002093EB0045 +:103AB00091919093EC003093ED008F5F873089F700 +:103AC0008EE78093EA001092EA008F898093490480 +:103AD00093C08B8D9C8D1092E9001092EC05109292 +:103AE000EB059093EA058093E905898D811156C015 +:103AF0008E899D89913A59F4813209F081C047E05D +:103B000050E065E271E080E00E940F1C75C09132C8 +:103B100009F076C0833289F4888D90E0982F882749 +:103B20002F89822BA0E0B0E08093210190932201A5 +:103B3000A0932301B09324015FC0803269F4809187 +:103B4000E80082FFFCCF67E085E291E00E94021569 +:103B50008BEF8093E80006C0823209F04DC08F8958 +:103B600080932C0180912F04882319F0EEEFFAE066 +:103B700002C0E0E0F8E08091250190912601A0913B +:103B80002701B0912801803B9440A105B10509F0BF +:103B90007BC080912C0180FF93C076C00E94F815F5 +:103BA000DC0112960D911C9113970115110541F13D +:103BB000D801ED91FC910190F081E02DBE016B5E8A +:103BC0007F4FC8010995811117C0F8010085118543 +:103BD000ECCF113009F44EC0133091F48F89882353 +:103BE00009F445C0823081F440E86DE083E292E060 +:103BF0000E94E419882321F08EEF8093E80079C0B9 +:103C000081E28093EB0075C0813029F440E86BE0DD +:103C100087E192E0EDCF833099F70E94F815DC013F +:103C20001296ED90FC9013978E010F5F1F4F680165 +:103C3000E114F10479F0D701ED91FC910680F78150 +:103C4000E02DB801C7010995080F111DF701E084A7 +:103C5000F184EECFD8011C92F60101900020E9F723 +:103C60003197BF016C197D0940E0C601C1CF61E009 +:103C700072E002C065E072E06115710509F2FB01B6 +:103C8000449150E080E840CF0FB6F894A895809119 +:103C90006000886180936000109260000FBEA8955C +:103CA000EE3F2AE0F20739F08091FE0A9091FF0A78 +:103CB00091838083A1CF1092FF0A1092FE0A9CCFBD +:103CC000EE3F8AE0F80731F0808191819093FF0AFE +:103CD0008093FE0A87E797E7918380839BE088E1E2 +:103CE0000FB6F894A895809360000FBE9093600083 +:103CF00083CF6C960FB6F894DEBF0FBECDBFDF91B9 +:103D0000CF91FF91EF91BF91AF919F918F917F9153 +:103D10006F915F914F913F912F911F910F91FF9064 +:103D2000EF90DF90CF900F900FBE0F901F901895DF +:103D300061E084E10E94A1168FEB94E00197F1F716 +:103D400060E084E10E94A11687E49EE00197F1F70C +:103D500060E084E10C94A11661E084E10E94A11668 +:103D600087E49EE00197F1F760E084E10E94A116EC +:103D70008FEB94E00197F1F760E084E10C94A116D9 +:103D800060E084E10E94A11687EB91E00197F1F7D2 +:103D9000089561E084E10E94A11687EB91E001970C +:103DA000F1F708957F928F929F92AF92BF92CF9238 +:103DB000DF92EF92FF920F931F93CF93DF93EC016B +:103DC00081E090E09093F0058093EF057E01BE01C5 +:103DD000685F7F4FFE012FEF3FEFE617F70799F07F +:103DE0008191382788E090E0A901440F551F37FFE3 +:103DF00006C09A01A1E22A27A0E13A2701C09A0150 +:103E0000019791F7EACF288739870E94C01E0E9448 +:103E1000C91E0E94C01E0E94C91E0E94C01E0E9490 +:103E2000C91E0E94C01E0E94C91E0E94C01E0E9480 +:103E3000C91E0E94C01E0E94C91E0E94C01E0E9470 +:103E4000C01E0E94C91E0E94C91E0E94C91E0E9457 +:103E5000C91E0E94C91E0E94C91E0E94C91E0E943E +:103E6000C91E0E94C91E2A9607EB11E093E7A92EEE +:103E700093E0B92E88248394912CF70171907F01EF +:103E800088E0C82ED12C8091EF059091F00577FE47 +:103E90000EC0892B31F060E084E10E94A116C501BB +:103EA00027C061E084E10E94A116C5010EC0892BE4 +:103EB00099F060E084E10E94A116C8010197F1F732 +:103EC00061E084E10E94A116C8010197F1F7909288 +:103ED000F0058092EF0512C061E084E10E94A11616 +:103EE000C8010197F1F760E084E10E94A116C801C2 +:103EF0000197F1F71092F0051092EF05770CF1E0C1 +:103F0000CF1AD10809F0BFCFEC16FD0609F0B5CFE6 +:103F100061E084E10E94A1168FE295E00197F1F73C +:103F200060E084E1DF91CF911F910F91FF90EF90BE +:103F3000DF90CF90BF90AF909F908F907F900C9428 +:103F4000A116AF92BF92CF92DF92EF92FF920F93A2 +:103F50001F93CF93DF9300D000D0CDB7DEB78A0197 +:103F600024E1A22EB12C21E0A21AB1086B017C0140 +:103F70000A2C04C0F694E794D794C7940A94D2F715 +:103F800069837A838B839C83C0FE07C00E94AC1E2A +:103F900069817A818B819C8106C00E94981E9C81D8 +:103FA0008B817A816981A114B104E9F684E0E82E5D +:103FB000F12C81E0E81AF108C8010E2C02C0959599 +:103FC00087950A94E2F780FF03C00E94AC1E02C0EE +:103FD0000E94981EE114F10461F70F900F900F906A +:103FE0000F90DF91CF911F910F91FF90EF90DF9095 +:103FF000CF90BF90AF900C94981E0F931F93CF93C8 +:10400000DF938C0185E30E94A10FC3E8DCE0CE01C1 +:104010000197F1F7C8010E94D21E86E30E94A10F0A +:1040200061E470E080E090E00E94321785E30E9436 +:10403000A10F2197F1F7C8010E94D21E86E30E94CA +:10404000A10F61E470E080E090E0DF91CF911F91DB +:104050000F910C943217CF92DF92EF92FF920E9451 +:10406000473126E03EE546EC53E40E94E4320E94EC +:1040700056336B017C01B701882799278DE00E9498 +:10408000870F99278F2D7E2D6D2D8EE00E94870F33 +:104090006C2D8FE0FF90EF90DF90CF900C94870F06 +:1040A00085E190E090937605809375050E94381025 +:1040B0006FEF8FEF0E94D10F60E977E78EED99E106 +:1040C0000E942B2064E087E00E94870F85E30E9416 +:1040D000A10F6DE080E00C94870F85E190E0909354 +:1040E0007605809375050E9438106FEF8FEF0E9460 +:1040F000D10F6091060170910701809108019091A4 +:1041000009010E942B2064E087E00E94870F85E36D +:104110000E94A10F6DE080E00C94870F85E190E094 +:1041200090937605809375050E9438106091060182 +:104130007091070180910801909109010E942B2044 +:1041400064E087E00E94870F6DE080E00E94870FA7 +:1041500067E080E10E94870F63E981E10E94870F99 +:1041600084E30C94A10F4F925F926F927F928F9293 +:104170009F92AF92BF92CF92DF92EF92FF920F93F6 +:104180001F93CF93DF93CDB7DEB7E9970FB6F894BF +:10419000DEBF0FBECDBF85E190E0909376058093A2 +:1041A00075050E94381086E30E94A10F60910201FC +:1041B0007091030180910401909105010E942B20D0 +:1041C00085E30E94A10F61E084E10E94A11687EBC4 +:1041D0009FEF9093F2058093F105EE24E394F12C88 +:1041E0008091240490912504009709F4AFC1813097 +:1041F000910541F0029709F08AC161E084E10E94D3 +:10420000A11685C1C114D10449F080912A0490916E +:104210002B04A0912C04B0912D0408C08091260499 +:1042200090912704A0912804B09129048093020161 +:1042300090930301A0930401B093050181E0C82687 +:1042400081E0C822DD2486E30E94A10F6091020173 +:104250007091030180910401909105010E942B202F +:1042600084E30E94A10F62E070E080E090E00E9491 +:10427000321760E0809175050E94A11684EF0E94BC +:10428000810F80E00E94810F082F61E08091750509 +:104290000E94A11610E0013811052CF01A9517FFA5 +:1042A00002C00F5F1F4F159507950B5411098091A0 +:1042B000F1059091F205801791070CF0BFC086E3DD +:1042C0000E94A10F6091020170910301809104018D +:1042D000909105010E942B2085E30E94A10F61E0CF +:1042E00084E10E94A11665E070E080E090E00E9409 +:1042F000321760E084E10E94A1160E941C184B0155 +:104300005C010E941C184090440450904504609049 +:10431000460470904704DC01CB0184199509A60975 +:10432000B70986399105A105B10508F48AC06091E5 +:1043300002017091030180910401909105011FA673 +:104340001EA619AA18AA1BAA1AAA2AE0AE014F5F34 +:104350005F4F0E94CB2FBE016F5F7F4FCE018E96C5 +:104360000E94BB1A23E030E040E050E0BE01625DF5 +:104370007F4FCE01C4960E94571B19A618A61BA6F4 +:104380001AA61DA61CA64AE0BE016F5F7F4FC8019A +:104390000E94A92FBE016F5F7F4FCE0188960E94B9 +:1043A000BB1A60EF73E0CE0182960E94421BBE01F1 +:1043B000685D7F4FCE0182960E94991A6FEF73E07D +:1043C0000E94801ABE016C5C7F4F0E94991A68E0BF +:1043D00074E00E94801ABC01CE0101960E94281B45 +:1043E000CE0182960E940B1BCE0188960E940B1B69 +:1043F000CE01C4960E940B1BCE018E960E940B1B11 +:10440000BE016F5F7F4F80E594E00E940F156AE167 +:1044100072E080E594E00E941D150E941C184B017B +:104420005C01609344047093450480934604909328 +:104430004704CE0101960E940B1B03C0FF2009F424 +:1044400066C00E941C18DC01CB0188199909AA09D1 +:10445000BB09893C9105A105B10508F06DC0EE20AE +:1044600009F453C060EF73E080E594E00E94F61514 +:10447000A801110F660B770B2AE030E080E594E08D +:104480000E947B156FEF73E080E594E00E94F615C3 +:1044900060910201709103018091040190910501E6 +:1044A0001BA21AA21DA21CA21FA21EA22AE0AE01DC +:1044B0004F5F5F4F0E94CB2FBE016F5F7F4FCE01DA +:1044C00082960E94BB1A23E030E040E050E0BE013B +:1044D0006E5D7F4FCE0101960E94571BBE016F5F3C +:1044E0007F4F80E594E00E940F15CE0101960E9457 +:1044F0000B1BCE0182960E940B1B68E074E080E5E6 +:1045000094E00E94E215E12C1FC0FF24F39480E5A3 +:1045100094E00E94A713181619060CF061CE1092B1 +:104520002504109224040E948E2063E773E080E546 +:1045300094E00E94E21554CE6CE074E080E594E0D3 +:104540000E94E215EE24E394F12CE1CFE9960FB638 +:10455000F894DEBF0FBECDBFDF91CF911F910F91B9 +:10456000FF90EF90DF90CF90BF90AF909F908F9093 +:104570007F906F905F904F900895DC01FB01129641 +:104580008C91129790E02481358182179307D1F4A2 +:1045900091818081813A31F481E0913091F09330C2 +:1045A00089F411C0813271F49B3021F482811F960D +:1045B0008C9305C09A3031F4828150968C9381E0BF +:1045C0000895089580E00895DC01FB0188E480836C +:1045D00089E4818384E482831D969C911D979F705A +:1045E0009F5B93831D968D919C911E9724E09695D9 +:1045F00087952A95E1F78F708F5B848385E0089516 +:10460000FC0182818F5BFB01808381E00895089526 +:1046100080E090E00895EF92FF920F931F93CF9365 +:10462000DF93FB012081213851F52381223239F5B6 +:10463000DC0112962C9130E04481558142175307DA +:10464000F1F4EC010B851C85E12CF12C0115110511 +:1046500091F0F801448155816281738180E80E9464 +:104660000F1C8F3FFFEF9F0769F0E80EF91ED8017E +:104670000D911C91EBCF81E08F87C70105C080E0D1 +:1046800090E002C08FEF9FEFDF91CF911F910F91CC +:10469000FF90EF900895CF93DF93CDB7DEB7699782 +:1046A0000FB6F894DEBF0FBECDBFFC01DB018C91CD +:1046B0008F5F8C93BE016F5F7F4F89E1DB011D929D +:1046C0008A95E9F729E0298384E08A8391E09D8334 +:1046D00083E08E832A8721E22B879C879D879F8793 +:1046E00022E2288B27E02B8B25E02C8B8E8B20E47D +:1046F00030E0388F2F8B998F82818B8395858685CB +:10470000998B8A8B838180688D8B49E150E080E0B2 +:104710000E940F1C69960FB6F894DEBF0FBECDBF86 +:10472000DF91CF9108952F923F924F925F926F92B7 +:104730007F928F929F92AF92BF92CF92DF92EF9231 +:10474000FF920F931F93CF93DF93CDB7DEB765979B +:104750000FB6F894DEBF0FBECDBF0E940D176B01E0 +:104760007C0180911B0890911C082601481A590A67 +:104770002DEC421620E1520608F4F6C08091950710 +:1047800090919607A201481B590BCA0157FF03C01D +:10479000919581959109883C91050CF0E1C080913B +:1047A00093079091940701969093940780939307B1 +:1047B000029709F0D5C094E6692E91E0792E01E0C8 +:1047C00010E020909107309092073B862A8649E0BE +:1047D00050E0B301CE0101960E94A02F8C816B8125 +:1047E000681708F4682F70E08091950790919607FC +:1047F0000E9485339B014091180150911901649FDB +:10480000C001659F900D749F900D112464E670E0C7 +:104810000E9485338985811103C0A1E0B0E002C008 +:10482000A2E0B0E08D81829FA001839F500D1124F2 +:104830005D874C878E81829F1001839F300C1124ED +:104840003F862E868F81829FA001839F500D112469 +:10485000598B488B8885829F1001839F300C1124CF +:104860003B8A2A8AFD01EE0FFF1FEB56F84F812C81 +:10487000912C54014A855B85415051095D8B4C8BCD +:104880008C899D89A817B90708F040C0880C991C2D +:10489000AA1CBB1C80819181AC012C843D844219EF +:1048A000530957FF03C051954195510946175707C2 +:1048B00070F4428153812E843F844219530957FF7B +:1048C00003C051954195510946175707E0F02888D4 +:1048D00039888219930997FF03C0919581959109B1 +:1048E0008617970780F5828193814A895B89841BAB +:1048F000950B97FF03C091958195910986179707AE +:1049000010F5689480F812963496BACF4A855B8584 +:1049100048305105C0F08092660590926705A092DC +:104920006805B09269051C013694279430924F04B3 +:1049300020924E043093900720938F0710934304E6 +:104940000093420409C00F5F1F4F59E0650E711CB0 +:104950000830110509F035CF109294071092930793 +:10496000109292071092910780919107909192076F +:104970008334910540F010929207109291071092A3 +:1049800094071092930780919107909192079C0150 +:104990002F5F3F4F3093920720939107880F991F05 +:1049A000FC01EB56F84F51824082C0921B08D09216 +:1049B0001C08E0921D08F0921E0865960FB6F89448 +:1049C000DEBF0FBECDBFDF91CF911F910F91FF9042 +:1049D000EF90DF90CF90BF90AF909F908F907F909F +:1049E0006F905F904F903F902F900895CF92DF92FD +:1049F000EF92FF920F931F93CF93DF93CDB7DEB764 +:104A0000CC54D1090FB6F894DEBF0FBECDBF8C01D8 +:104A10006B016CE172E0CE01895B9F4F0E94421BEB +:104A2000F601E480F5806CE172E0CE018F5B9F4F70 +:104A30000E94421BFCE1EF16F104B9F52BE1E22ED6 +:104A4000F12CB701C6010E94211AFC016081CE0140 +:104A500001960E94101BBE016F5F7F4FCE018F5BDE +:104A60009F4F0E94D21ACE0101960E940B1B61E259 +:104A700074E0CE018F5B9F4F0E94331A6DE872E0A5 +:104A8000811109C0CE018F5B9F4F0E94331A88238A +:104A900039F061E274E0CE01895B9F4F0E94AC1A4D +:104AA000F1E0EF1AF10868F676C0E0E2EE16F104E4 +:104AB000B9F59FE1E92EF12CB701C6010E94211A38 +:104AC000FC016081CE0101960E94101BBE016F5F48 +:104AD0007F4FCE018F5B9F4F0E94D21ACE0101966D +:104AE0000E940B1B61E274E0CE018F5B9F4F0E941E +:104AF000331A6DE872E0811109C0CE018F5B9F4FC0 +:104B00000E94331A882339F061E274E0CE01895B98 +:104B10009F4F0E94AC1AF1E0EF1AF10868F63BC013 +:104B2000E4E0EE16F10409F04CC083E0E82EF12C2D +:104B3000B701C6010E94211AFC016081CE010196D5 +:104B40000E94101BBE016F5F7F4FCE018F5B9F4F96 +:104B50000E94D21ACE0101960E940B1B61E274E002 +:104B6000CE018F5B9F4F0E94331A6DE872E0811176 +:104B700009C0CE018F5B9F4F0E94331A882339F002 +:104B800061E274E0CE01895B9F4F0E94AC1AF1E0B4 +:104B9000EF1AF10868F642E050E060E070E0299614 +:104BA0008EAD9FAD29970E94672E20E1AE014F5F29 +:104BB0005F4F0E94CB2FBE016F5F7F4FC8010E94E5 +:104BC000421BCE018F5B9F4F0E940B1BCE01895B66 +:104BD0009F4F0E940B1BC801C45BDF4F0FB6F894B8 +:104BE000DEBF0FBECDBFDF91CF911F910F91FF9020 +:104BF000EF90DF90CF9008958F929F92AF92BF92E7 +:104C0000CF92DF92EF92FF920F931F93CF93DF9398 +:104C1000CDB7DEB76E970FB6F894DEBF0FBECDBF2F +:104C20000E940D176B017C0180918B0790918C077E +:104C30009601281B390BC90130938A0720938907F5 +:104C400020918707309188072C39310508F4FFC07F +:104C50002091F7053091F805A901405A5F404817A7 +:104C6000590708F0F4C02056304F8217930708F018 +:104C7000EEC020912706309128062D5A3D40273E50 +:104C8000334008F0E4C06CE172E0CE0149960E9426 +:104C9000421B6CE172E0CE0143960E94421B6CE124 +:104CA00072E0CE010D960E94421B09E216E0F80167 +:104CB00020813181828193812817390718F461E2BC +:104CC00074E005C08217930730F46DE872E0CE01FE +:104CD00043960E94AC1A0C5F1F4FF6E0093A1F077B +:104CE00031F709EA16E0F801208131818281938150 +:104CF0002817390718F461E274E005C0821793079A +:104D000030F46DE872E0CE0149960E94AC1A0C5F57 +:104D10001F4FF7E009311F0731F709E117E0F801EC +:104D200020813181828193812817390718F461E24B +:104D300074E005C08217930730F46DE872E0CE018D +:104D40000D960E94AC1A0C5F1F4FF7E009321F0747 +:104D500031F7BE01635F7F4FCE0107960E94281B8B +:104D6000BE01695F7F4FCE0101960E94F624BE010D +:104D70006F5F7F4F84E995E00E94D21ACE010196C1 +:104D80000E940B1BCE0107960E940B1BBE016D5E9D +:104D90007F4FCE0107960E94281BBE01695F7F4F9F +:104DA000CE0101960E94F624BE016F5F7F4F8AE913 +:104DB00095E00E94D21ACE0101960E940B1BCE01F3 +:104DC00007960E940B1BBE01675E7F4FCE010796C0 +:104DD0000E94281BBE01695F7F4FCE0101960E9491 +:104DE000F624BE016F5F7F4F80EA95E00E94D21AE1 +:104DF000CE0101960E940B1BCE0107960E940B1B51 +:104E0000812C912C540183948092620590926305C9 +:104E1000A0926405B092650584E090E09093F4055B +:104E20008093F305CE010D960E940B1BCE01439695 +:104E30000E940B1BCE0149960E940B1B80926205BB +:104E400090926305A0926405B092650503C0893C09 +:104E5000924320F01092880710928707809187076D +:104E600090918807883C910540F010928807109235 +:104E700087071092F6051092F505809187079091AB +:104E800088079C012F5F3F4F309388072093870747 +:104E9000880F991FFC01E950FA4F80918907909182 +:104EA0008A0791838083C0928B07D0928C07E0920F +:104EB0008D07F0928E076E960FB6F894DEBF0FBE88 +:104EC000CDBFDF91CF911F910F91FF90EF90DF90B9 +:104ED000CF90BF90AF909F908F9008950F931F93A6 +:104EE000CF93DF931F92CDB7DEB78B0180914E0534 +:104EF000811107C08DE395E00E94351981E0809310 +:104F00004E0582E0898341E050E0BE016F5F7F4F34 +:104F1000809140050E946C1797FD08C08091400564 +:104F200048E050E0B80180640E946C170F90DF9158 +:104F3000CF911F910F910895DC01683810F06858E7 +:104F40002DC0E62FF0E067FF11C0E058F10981E0C5 +:104F500090E001C0880FEA95EAF714969C911497A7 +:104F6000892B14968C93149760E018C0EF5CFD4F6A +:104F70006491611109C081E090E013969C938E9337 +:104F8000129780E090E0089567FF08C014968C9116 +:104F90001497826014968C9314976F7716968C9161 +:104FA0001697861751F117968C911797861729F146 +:104FB00018968C911897861701F119968C9119976C +:104FC0008617D9F01A968C911A978617B1F01B960E +:104FD0008C911B97861789F0FD01369680E090E052 +:104FE0002191211105C0FD01E80FF91F668305C05D +:104FF000019686309105A1F7BECFCD01BD016C5F52 +:105000007F4F0E946E2781E090E00895EF92FF921B +:105010000F931F93CF938C01C62F0E949C277C0176 +:10502000C83818F068E76C0F1FC0EC2FF0E0C7FF1E +:105030000FC0E058F10921E030E001C0220FEA95ED +:10504000EAF72095F80184812823248360E00CC0CE +:10505000EF5CFD4F64916623D1F067FF05C0F80156 +:1050600084818D7F84836F77F801369686E066238E +:1050700021F09081961301C01082815031968111E8 +:10508000F6CFB8016C5F7F4FC8010E946E27C70141 +:105090009927CF911F910F91FF90EF900895CF9393 +:1050A000DF93CDB7DEB7E0970FB6F894DEBF0FBE43 +:1050B000CDBF789484B5826084BD84B5816084BDA1 +:1050C00085B5826085BD85B5816085BD80916E00A6 +:1050D000816080936E0010928100809181008260D7 +:1050E0008093810080918100816080938100809114 +:1050F0008000816080938000809191008260809325 +:105100009100809191008160809391008091900046 +:105110008160809390008091C10084608093C10081 +:105120008091C10082608093C1008091C100816044 +:105130008093C1008091C30081608093C3008091FF +:10514000C00082608093C0008091C2008160809323 +:10515000C20080917A00846080937A0080917A0006 +:10516000826080937A0080917A00816080937A00D7 +:1051700080917A00806880937A001092490410929E +:105180003104109230048091D70081608093D70061 +:1051900080EA8093D80089B5806189BD89B5826035 +:1051A00089BD09B400FEFDCF61E070E080E090E0D1 +:1051B0000E9432178091D8008F7C80618093D80044 +:1051C0008091E000807F8093E0008091E1008E7EFE +:1051D0008093E1008DE08093E200559A209A5D98DB +:1051E0002898EEEFFFE7859194918B3F9C4D19F441 +:1051F00081E080932F04E0916004F091610482E0EB +:105200008083E0915C04F0915D041082E0915E0483 +:10521000F0915F048FEC808310926804E091640445 +:10522000F091650486E08083E0916204F09163046C +:10523000808180618083E0916204F09163048081C9 +:1052400088608083E0916204F091630480818068CB +:105250008083E0916204F091630480818F7D80837C +:1052600060ED77E080E090E00E94321761E082E13B +:105270000E94D11661E083E10E94D11661E085E1D0 +:105280000E94D11661E084E10E94D11660E082E0C4 +:105290000E94D11661E085E10E94A11660E084E1E0 +:1052A0000E94A11661E085E10E94A11660E084E100 +:1052B0000E94A11661E085E10E94D11661E084E1BF +:1052C0000E94D11660E082E00E94D11661E088E081 +:1052D0000E94D11661E088E00E94A11660E085E09E +:1052E0000E94D11661E086E00E94D11661E089E05B +:1052F0000E94D11660E086E00E94A11660E089E07D +:105300000E94A11664E670E080E090E00E943217EF +:1053100060E173E080E594E00E94E2150E948E2037 +:1053200064E070E080E090E00E94321761E383E285 +:1053300093E00E942B0E6AE086E293E00E942B0E1F +:1053400043E050E06DE089E293E00E94D61262E211 +:105350008EE293E00E942B0E42E050E060E189E390 +:1053600093E00E94D61241E050E068E083E493E0CD +:105370000E94D61281E090E09093800580937F0593 +:105380000E941411ABEF2A2EA4E03A2E0E941C18A2 +:105390004B015C010E941C18DC01CB0188199909A2 +:1053A000AA09BB0985369105A105B10508F06FC0B2 +:1053B00009EE13E00E944B11892B19F401501109D9 +:1053C000C9F7C1010197F1F70E944B11019711F73D +:1053D00018E0F9EEAF2EF3E0BF2E0E944B110197BB +:1053E00029F431E0A31AB108C1F751C0C1010197F6 +:1053F000F1F70E944B11892B09F449C0115049F76C +:1054000009EE13E00E944B11019709F485C2512C5B +:105410001D821C821B821A82198200E010E030E09B +:10542000AE014F5F5F4F5A01412C60E0C10101970F +:10543000F1F738AB6DA70E944B1121E038A96DA59B +:10544000892B09F420E0822E912C643009F06BC284 +:10545000420ED5018C91280FF50121935F0149EE91 +:10546000642E43E0742E38AB6DA70E944B1138A90F +:105470006DA58815990509F46BC251106EC26F5F56 +:105480006530A1F63A3009F46DC240FE69C28091E0 +:10549000320490913304009709F49EC08130910545 +:1054A000D1F0029709F085C08091380490913904B9 +:1054B000A0913A04B0913B0489A79AA7ABA7BCA7D7 +:1054C0004090340450903504609036047090370456 +:1054D0000FE010E00FC040913E0450913F046091F6 +:1054E00040047091410480913C0490913D040E94DD +:1054F000CE115FC080903E0490903F04A090400485 +:10550000B0904104B501A40180913C0490913D0408 +:105510000E94CE110150110969F7A50194012419C7 +:10552000350946095709A4E6B0E00E94933229A53F +:105530003AA54BA55CA524193509460957090E94CF +:10554000743263E673E080E594E02DA738AB4EA794 +:105550005FA70E94F6152DA538A9B901653671051A +:1055600014F064E670E04AE050E080E594E00E94C8 +:10557000C91580913E0490913F04A0914004B091E0 +:10558000410429A53AA54BA55CA582179307A4075A +:10559000B50721F410923304109232040196A11D34 +:1055A000B11D80933E0490933F04A0934004B093B8 +:1055B000410480E594E00E94A713181619060CF028 +:1055C00066CF109233041092320463E773E080E5F3 +:1055D00094E00E94E2155BCF80E594E00E94A7135F +:1055E00018161906B4F480E594E00E9485138983A7 +:1055F0001A8241E050E0BE016F5F7F4F8EE895E078 +:105600000E94521A64E070E080E090E00E9432173D +:10561000E3CF8091920590919305892B11F00E9420 +:10562000850180910A0190910B018130910509F06B +:10563000BCC08091660590916705A0916805B09106 +:105640006905892B8A2B8B2B09F463C10E941C18D6 +:105650000091440410914504209146043091470480 +:10566000DC01CB01801B910BA20BB30B8E3591405B +:10567000A105B10548F410926605109267051092D5 +:1056800068051092690545C168E773E080E594E01C +:105690000E94F61560910601709107018091080142 +:1056A000909109011CA21BA21EA21DA218A61FA256 +:1056B0002AE0AE014F5F5F4F0E94B42FBE016F5FC3 +:1056C0007F4FCE0183960E94BB1A23E030E040E07A +:1056D00050E0BE016D5D7F4FCE0101960E94571BC9 +:1056E000BE016F5F7F4F80E594E00E940F15CE01F1 +:1056F00001960E940B1BCE0183960E940B1B6BE848 +:1057000073E080E594E00E94F615409142045091C8 +:10571000430460E070E02AE080E594E00E943215E6 +:105720006CE973E080E594E00E94F615409166050F +:105730005091670560916805709169054F70552714 +:105740006627772720E180E594E00E9432156CE51A +:1057500073E080E594E00E94F615809166059091D3 +:105760006705A0916805B0916905BC01CD0124E0F1 +:1057700096958795779567952A95D1F740E150E002 +:105780000E945E0F109266051092670510926805E0 +:10579000109269050E941C1860934404709345049C +:1057A0008093460490934704B4C0029709F0B1C0B7 +:1057B0008091620590916305A0916405B0916505A3 +:1057C000892B8A2B8B2B09F4A4C0E99881E994E1F9 +:1057D00090930F0180930E016AE975E0CE01019666 +:1057E0000E94281B40E150E060E070E089819A81CE +:1057F0000E94672ECE0101960E940B1B62EB73E0A4 +:1058000080E594E00E94F61565E873E080E594E099 +:105810000E94F615609106017091070180910801C0 +:10582000909109011CA21BA21EA21DA218A61FA2D4 +:105830002AE0AE014F5F5F4F0E94B42FBE016F5F41 +:105840007F4FCE0183960E94BB1A23E030E040E0F8 +:1058500050E0BE016D5D7F4FCE0101960E94571B47 +:10586000BE016F5F7F4F80E594E00E940F15CE016F +:1058700001960E940B1BCE0183960E940B1B60ECCD +:1058800073E080E594E00E94F6156DE573E080E535 +:1058900094E00E94F6156AE975E0CE0101960E9437 +:1058A000281BBE016F5F7F4F80E594E00E940F15BB +:1058B000CE0101960E940B1B61EE73E080E594E03F +:1058C0000E94F61560EA75E0CE0101960E94281B41 +:1058D000BE016F5F7F4F80E594E00E940F15CE01FF +:1058E00001960E940B1B6CE172E080E594E00E943F +:1058F000E2151092620510926305109264051092F1 +:10590000650581E090E090936B0580936A050E94A5 +:10591000430F0E9447143ACD0150110909F072CD8E +:105920005524539475CD3A3009F492CD323048F075 +:10593000CC0CDD1CEE1CFF1CC20ED11CE11CF11CAA +:1059400087CDA801440F551F8A01080D191D80CD70 +:10595000F1E06F1A710809F086CD5524539492CD69 +:10596000511095CD3F5F3B3009F05ACD51108FCD8E +:10597000898180FD8CCD8A8180FD89CD8B8180FDE0 +:1059800086CD8C8180FD83CD11270E941C188090CC +:10599000440490904504A0904604B0904704DC0174 +:1059A000CB0188199909AA09BB098E359140A10537 +:1059B000B10508F46CCDC114D104E104F10409F47B +:1059C00066CD6DE473E080E594E00E94F615A801D1 +:1059D000110F660B770B2AE030E080E594E00E941F +:1059E0007B156CE573E080E594E00E94F6154AE0D3 +:1059F00050E0C701B6010E945E0F0E941C18609320 +:105A00004404709345048093460490934704C12C4A +:105A1000D12C76013CCD86EB95E00E940B1B8EE8E5 +:105A200095E00E940B1B84E995E00E940B1B8AE91C +:105A300095E00E940B1B80EA95E00C940B1B0F93E2 +:105A40001F93CF93DF93109253041092520488EE69 +:105A500093E0A0E0B0E08093540490935504A093A9 +:105A60005604B093570427E431E030935104209357 +:105A700050042DEC30E030935D0420935C042CEC5A +:105A800030E030935F0420935E0428EC30E03093E4 +:105A900061042093600429EC30E030936304209388 +:105AA00062042AEC30E030936504209364042EEC09 +:105AB00030E03093670420936604109269041092DA +:105AC0006A0410926B0410926C041092F00410920D +:105AD000EF048093F1049093F204A093F304B09345 +:105AE000F40489E591E09093EE048093ED048FEF48 +:105AF0009FEF9093FA048093F90410925905109245 +:105B000058058BE691E09093570580935605809158 +:105B1000AE05811113C01092A9051092A80585E366 +:105B200091E09093AB058093AA058FE290E090936B +:105B3000AD058093AC0581E08093AE0580914E0564 +:105B4000811107C08DE395E00E94351981E08093B3 +:105B50004E05E0914805F0914905309739F488EAFF +:105B600095E090934905809348050AC08081918112 +:105B7000009711F0FC01FACF88EA95E091838083C9 +:105B80002091AC053091AD0580914A0590914B056F +:105B9000820F931F90934B0580934A056CE172E04E +:105BA00080EA95E00E94421B6CE172E08AE995E090 +:105BB0000E94421B6CE172E084E995E00E94421B66 +:105BC0006CE172E08EE895E00E94421BCFEFDFEFC0 +:105BD000D0938205C09381050AE010E010938405FC +:105BE0000093830549E050E064E671E085E895E0C4 +:105BF0000E94A02FD0938005C0937F058CE390E096 +:105C00009093190180931801109266051092670510 +:105C1000109268051092690510937605009375053A +:105C200022E030E03093780520937705D0936D051E +:105C3000C0936C0524E030E030937105209370052B +:105C400021E02093720525EF30E030936F0520931B +:105C50006E05D0936B05C0936A05909317018093EE +:105C6000160110926205109263051092640510925D +:105C7000650583E190E09093BD058093BC0582E1CA +:105C800090E09093BF058093BE051092C20580E21C +:105C90008093C3051092C40585E08093CA0585E012 +:105CA00090E0A0E0B0E08093D0059093D105A09360 +:105CB000D205B093D3051092C5056CE172E086EB76 +:105CC00095E0DF91CF911F910F910C94421BA6E0BC +:105CD000B0E0EDE6FEE20C949E325C016B017A01CD +:105CE0006115710519F0DB018D939C93E114F104AA +:105CF00029F0C7010297839708F0DCC03501BFEF98 +:105D00006B1A7B0AF5011081812F90E00E94972F7A +:105D1000892B11F05301F2CF1D3249F43501F2E025 +:105D20006F0E711CD50111961C9101E009C01B3248 +:105D300031F43501B2E06B0E711CF501118100E008 +:105D4000E114F10409F4C4C0F0E1EF16F10489F4A0 +:105D5000103399F5D3018C918F7D883509F0B2C04D +:105D600011961C91B2E06B0E711C026050E1E52EA1 +:105D7000F12CEAE0EE16F10409F4B0C0F0E1EF1600 +:105D8000F104D9F028E0E216F10451F438E0E32EF2 +:105D9000F12C88248A94982CA82C4FE1B42E13C09F +:105DA0006FEF7FEFCB0197010F2C000C440B550BCD +:105DB0000E94523249015A0106C088248A94982CC4 +:105DC000A82C2FE0B22E7E826D8260E020E030E0D1 +:105DD000A90127010F2C000C660877082D803E8052 +:105DE000E0EDE10FEA3060F08FEB810F8A3110F4C3 +:105DF000E9EC05C08FE9810F8A3190F5E9EAE10FFE +:105E00008E2F90E08E159F055CF56F3F09F182168D +:105E10009306A406B506D8F0C301B2010E9442322F +:105E20002E2F30E040E050E029833A834B835C839F +:105E3000260F371F481F591F89819A81AB81BC816A +:105E4000281739074A075B0710F061E001C06FEFC0 +:105E5000ED81FE813196FE83ED83D1011C91BECF91 +:105E6000C114D10489F0662339F08D819E81019798 +:105E7000F6019183808308C001FF06C08D819E8159 +:105E80000297D6018D939C9300FF07C050954095D3 +:105E9000309521953F4F4F4F5F4F67FF10C082E213 +:105EA00090E09093200880931F086FEF7FEF8FEFB3 +:105EB0009FEF1BC060E070E080E090E016C0B90189 +:105EC000CA0113C010E3E114F10409F45FCF51CF0C +:105ED000103309F43FCF9AE0E92EF12C89E9882E9E +:105EE000982CA82C89E1B82E6ECF2696E2E10C946E +:105EF000BA32FC0188279927E89421912032E9F3EE +:105F0000293010F02E30C8F32B3241F02D3239F405 +:105F1000689404C00E94C32F820F911D21912053C9 +:105F20002A30C0F31EF4909581959F4F08959111EA +:105F30000C943431803219F089508550C8F7089597 +:105F4000FB01DC0102C005900D9241505040D8F792 +:105F50000895BB274A3031F4992322F4BDE290958D +:105F600081959F4F0C94EE2FBB272A3051F4992333 +:105F700042F4BDE290958095709561957F4F8F4F6B +:105F80009F4F0C94CC2F7AE0979F902D879F802D68 +:105F9000910D11240895BB27FA01A62F62177105F0 +:105FA00081059105330B30FB66F0AA27660F771F3A +:105FB000881F991FAA1FA21710F0A21B63953850C3 +:105FC000A9F7A05DAA3308F0A95DA19336F7B11136 +:105FD000B1931082CA010C943731BB27FB015527BE +:105FE000AA27880F991FAA1FA41710F0A41B839536 +:105FF0005051B9F7A05DAA3308F0A95DA1930097AD +:1060000079F7B111B1931192CB010C943731CF9341 +:10601000DF938230910510F482E090E0E091230854 +:10602000F091240820E030E0C0E0D0E0309711F19A +:106030004081518148175907C0F04817590761F44A +:1060400082819381209719F09B838A832BC0909340 +:1060500024088093230826C02115310519F0421722 +:10606000530718F49A01BE01DF01EF010280F381AA +:10607000E02DDCCF2115310509F1281B390B243027 +:10608000310590F412968D919C91139761157105CD +:1060900021F0FB019383828304C0909324088093B2 +:1060A0002308FD01329644C0FD01E20FF31F8193E6 +:1060B0009193225031092D933C933AC020912108AD +:1060C00030912208232B41F420912F01309130018F +:1060D000309322082093210820912D0130912E0128 +:1060E0002115310541F42DB73EB740913101509152 +:1060F0003201241B350BE0912108F0912208E217B0 +:10610000F307A0F42E1B3F0B2817390778F0AC01DA +:106110004E5F5F4F2417350748F04E0F5F1F5093B7 +:106120002208409321088193919302C0E0E0F0E0BF +:10613000CF01DF91CF9108950F931F93CF93DF93FA +:10614000009709F48CC0FC013297138212820091EF +:106150002308109124080115110581F42081318153 +:10616000820F931F209121083091220828173907A8 +:1061700079F5F0932208E093210871C0D80140E03E +:1061800050E0AE17BF0750F412962D913C91139733 +:10619000AD012115310509F1D901F3CF9D01DA01D6 +:1061A0003383228360817181860F971F8217930743 +:1061B00069F4EC0128813981260F371F2E5F3F4F8C +:1061C000318320838A819B8193838283452B29F4A9 +:1061D000F0932408E093230842C01396FC93EE93B7 +:1061E0001297ED01499159919E01240F351FE21735 +:1061F000F30771F480819181840F951F02961196A7 +:106200009C938E938281938113969C938E93129785 +:10621000E0E0F0E0D80112968D919C9113970097E1 +:1062200019F0F8018C01F6CF8D919C9198012E5FA9 +:106230003F4F820F931F2091210830912208281789 +:10624000390769F4309729F4109224081092230832 +:1062500002C0138212821093220800932108DF915A +:10626000CF911F910F910895992788270895DC01F8 +:10627000FC01672F71917723E1F7329704C07C917D +:106280006D9370836291AE17BF07C8F30895E894C9 +:1062900009C097FB3EF490958095709561957F4F6E +:1062A0008F4F9F4F9923A9F0F92F96E9BB2793951C +:1062B000F695879577956795B795F111F8CFFAF42C +:1062C000BB0F11F460FF1BC06F5F7F4F8F4F9F4F5D +:1062D00016C0882311F096E911C0772321F09EE8BB +:1062E000872F762F05C0662371F096E8862F70E021 +:1062F00060E02AF09A95660F771F881FDAF7880FFB +:106300009695879597F908950E9497310C940832D5 +:106310000E94FA3138F00E94013220F0952311F0EA +:106320000C94F1310C94F73111240C943C320E94FE +:10633000193270F3959FC1F3950F50E0551F629F7E +:10634000F001729FBB27F00DB11D639FAA27F00DCE +:10635000B11DAA1F649F6627B00DA11D661F829FF5 +:106360002227B00DA11D621F739FB00DA11D621FDA +:10637000839FA00D611D221F749F3327A00D611DF7 +:10638000231F849F600D211D822F762F6A2F1124D9 +:106390009F5750409AF0F1F088234AF0EE0FFF1F0C +:1063A000BB1F661F771F881F91505040A9F79E3F63 +:1063B000510580F00C94F1310C943C325F3FE4F3D2 +:1063C000983ED4F3869577956795B795F795E795B9 +:1063D0009F5FC1F7FE2B880F911D9695879597F9C2 +:1063E000089597F99F6780E870E060E008959FEF57 +:1063F00080EC089500240A9416161706180609065C +:10640000089500240A94121613061406050608952A +:10641000092E0394000C11F4882352F0BB0F40F4B2 +:10642000BF2B11F460FF04C06F5F7F4F8F4F9F4FF2 +:10643000089557FD9058440F551F59F05F3F71F074 +:106440004795880F97FB991F61F09F3F79F08795DB +:106450000895121613061406551FF2CF4695F1DF64 +:1064600008C0161617061806991FF1CF86957105F4 +:10647000610508940895E894BB2766277727CB0128 +:1064800097F90895DB018F939F930E949332BF91F8 +:10649000AF91A29F800D911DA39F900DB29F900D73 +:1064A00011240895A1E21A2EAA1BBB1BFD010DC0E9 +:1064B000AA1FBB1FEE1FFF1FA217B307E407F507B4 +:1064C00020F0A21BB30BE40BF50B661F771F881F90 +:1064D000991F1A9469F760957095809590959B0126 +:1064E000AC01BD01CF010895052E97FB1EF4009469 +:1064F0000E948B3257FD07D00E94523207FC03D016 +:106500004EF40C948B3250954095309521953F4F29 +:106510004F4F5F4F089590958095709561957F4F8F +:106520008F4F9F4F08950E94D532A59F900DB49F25 +:10653000900DA49F800D911D112408952F923F92DC +:106540004F925F926F927F928F929F92AF92BF9283 +:10655000CF92DF92EF92FF920F931F93CF93DF932F +:10656000CDB7DEB7CA1BDB0B0FB6F894DEBF0FBE8C +:10657000CDBF09942A88398848885F846E847D84D9 +:106580008C849B84AA84B984C884DF80EE80FD80DB +:106590000C811B81AA81B981CE0FD11D0FB6F89451 +:1065A000DEBF0FBECDBFED010895A29FB001B39F26 +:1065B000C001A39F700D811D1124911DB29F700D0C +:1065C000811D1124911D08950E94F8320C94083207 +:1065D0000E94013258F00E94FA3140F029F45F3FE6 +:1065E00029F00C94F13151110C943C320C94F73198 +:1065F0000E94193268F39923B1F3552391F3951B47 +:10660000550BBB27AA2762177307840738F09F5FD3 +:106610005F4F220F331F441FAA1FA9F335D00E2E40 +:106620003AF0E0E832D091505040E695001CCAF7AD +:106630002BD0FE2F29D0660F771F881FBB1F261770 +:1066400037074807AB07B0E809F0BB0B802DBF0147 +:10665000FF2793585F4F3AF09E3F510578F00C9416 +:10666000F1310C943C325F3FE4F3983ED4F38695CD +:1066700077956795B795F7959F5FC9F7880F911D37 +:106680009695879597F90895E1E0660F771F881F23 +:10669000BB1F621773078407BA0720F0621B730BD6 +:1066A000840BBA0BEE1F88F7E09508950E94213203 +:1066B00088F09F5798F0B92F9927B751B0F0E1F0C3 +:1066C000660F771F881F991F1AF0BA95C9F714C073 +:1066D000B13091F00E943B32B1E008950C943B320E +:1066E000672F782F8827B85F39F0B93FCCF38695AC +:1066F00077956795B395D9F73EF490958095709509 +:1067000061957F4F8F4F9F4F0895AA1BBB1B51E18F +:1067100007C0AA1FBB1FA617B70710F0A61BB70B11 +:10672000881F991F5A95A9F780959095BC01CD01B6 +:106730000895EE0FFF1F0590F491E02D09940F933B +:10674000083090F0982F872F762F652F542F432FE6 +:10675000322F22270850F4CF220F331F441F551F1A +:10676000661F771F881F991F0A95B2F70F9108952A +:1067700097FB10F8169400080F93083098F0085013 +:10678000232F342F452F562F672F782F892F902DA9 +:10679000F4CF059497958795779567955795479585 +:1067A000379527950A95AAF70F9108952A0D3B1D55 +:1067B0004C1D5D1D6E1D7F1D801F911F08950024BF +:1067C000A7FD00942A1730054005500560057005A7 +:1067D000800590050895A0E0B0E0E1EFF3E30C94AC +:1067E000A232EC01009721F4CB010E940730B8C01F +:1067F000FC01E60FF71F9C0122503109E217F30755 +:1068000008F4ACC0D9010D911C9111970617170718 +:10681000B0F00530110508F49FC0C8010497861731 +:10682000970708F499C002501109061B170B019332 +:1068300011936D937C93CF010E949C308DC05B01BE +:10684000A01AB10A4C01800E911EA0912308B091AC +:10685000240840E050E0E12CF12C109709F44AC0E4 +:10686000A815B905D1F56D907C901197630182E070 +:10687000C80ED11CCA14DB0480F1A3014A195B09BC +:106880006A0182E0C80ED11C1296BC901297139632 +:10689000AC91B5E0CB16D10440F0B282A383518312 +:1068A0004083D9016D937C930AC00E5F1F4FC301D3 +:1068B000800F911FF90191838083EB2DFA2FE11452 +:1068C000F10431F0D7011396FC93EE93129744C074 +:1068D000F0932408E09323083FC08D919C91119779 +:1068E0004817590708F4AC017D0112960D90BC9130 +:1068F000A02DB3CF80912108909122088815990589 +:10690000E1F446175707C8F480912D0190912E01AC +:10691000009741F48DB79EB74091310150913201FB +:10692000841B950BE817F907C8F4F0932208E0934D +:106930002108F901718360830FC0CB010E940730E9 +:106940007C01009759F0A801BE010E94BA34CE0123 +:106950000E949C30C70104C0CE0102C080E090E0DC +:10696000CDB7DEB7EEE00C94BE3281E090E0F89453 +:106970000C94F834FB01DC0102C001900D924150EF +:106980005040D8F70895FC018191861721F08823A3 +:10699000D9F7992708953197CF010895FB01DC01BC +:1069A0008D91019080190110D9F3990B0895FB0185 +:1069B000DC0101900D920020E1F70895FB01519157 +:1069C0005523A9F0BF01DC014D9145174111E1F7B5 +:1069D00059F4CD010190002049F04D91401541112D +:1069E000C9F3FB014111EFCF81E090E001970895D9 +:1069F00011E0CAE5D1E004C0FE010E94993321965E +:0A6A0000CB35D107C9F7F894FFCF9A +:106A0A00FFFF0018DD19C084C61201009114911409 +:106A1A009114911491143C003C0000C18081000043 +:106A2A0000FFFFFFFF00E10000000000000000255A +:106A3A00088000E0B94C264080140000C000000025 +:106A4A0000000000000000DE134B1376132514A784 +:106A5A001385139913000000005114061872146765 +:106A6A00147714B61492140000000006284B130879 +:106A7A0023072300000000BD224B230B23E42248F6 +:106A8A004944005B4849445D6C6F636B005B48494D +:106A9A00445D636D61747269780068696400524686 +:106AAA00004A616D002C6672657100636C617373D4 +:106ABA0000536D617274002C6672657132006672E1 +:106ACA0065713100527564650054504D530054503D +:106ADA004D535F6F6B005472616E736D6974004C35 +:106AEA0069677468426172002C64617461002A5497 +:106AFA0072616E736D6974204C6967746842617261 +:106B0A002000467265713A002C446174613A002A89 +:106B1A005472616E736D697420000D0A00417474B9 +:106B2A0061636B002C7374617274002C656E64006F +:106B3A002C66756E630053746172743A002C456E4C +:106B4A00643A002C46756E633A005B52465D5B50B0 +:106B5A00726F67726573735D005377697463680057 +:106B6A00616374696F6E002A52465F506F7765726F +:106B7A00206F6666002A52465F506F776572206FF3 +:106B8A006E00536574757000434331313031002A09 +:106B9A0052465F736E69666665725F666978656498 +:106BAA00006B65656C6F71002A52465F736E696689 +:106BBA006665725F4B65656C6F71006E5246323462 +:106BCA004C3031004E46430073696D756C617469CF +:106BDA006F6E0076640061747461636B003B53747A +:106BEA006172742049443A003B454E442049443A74 +:106BFA000073776974636800777269746500772C2B +:106C0A0056443A006572726F723A002020202000C2 +:106C1A00437562656D696E692052756E696E672E7D +:106C2A002E2E0076720043480046524551004D6FA1 +:106C3A0064756C6174696F6E00446174612052619D +:106C4A00746500504B544354524C3020005B4E46FE +:106C5A00435D5B726561645D76643A002C646174BD +:106C6A00613A005B4E46435D5B70726F6772657393 +:106C7A00735D0065786974005B52465D5B536E69AB +:106C8A00666665725D667265713A002C70726F7421 +:106C9A006F636F6C3A46697865642D002C6D6F647A +:106CAA00756C6174696F6E3A61736B2C66756E638D +:106CBA003A005B52465D5B536E69666665725D00BB +:106CCA002C70726F746F636F6C3A6B65656C6F7161 +:106CDA002C6D6F64756C6174696F6E3A61736B2C9D +:106CEA00002C53657269616C4E756D6265723A006B +:106CFA005B52465D5B4A616D5D525353493A00648B +:106D0A00422C465245513A004D687A005B52465D24 +:106D1A005B4A616D5D4E6F74204A616D6D696E6785 +:046D2A000030000035 +:2070000055C000006EC000006CC000006AC0000068C0000066C0000064C0000062C0000043 +:2070200060C000005EC00000F2C400005AC0000058C0000056C0000054C0000052C00000EE +:2070400050C0000078C000004CC000004AC0000048C0000046C0000044C0000042C00000BE +:2070600040C000003EC000003CC000003AC0000038C0000036C0000034C0000032C0000048 +:2070800030C000002EC000002CC000002AC0000028C0000026C0000024C0000022C00000A8 +:2070A00020C000001EC000001CC0000011241FBECFEFDAE0DEBFCDBF11E0A0E0B1E0E2E3BC +:2070C000FFE702C005900D92A83AB107D9F711E0A8EAB1E001C01D92AE3BB107E1F78FD30B +:2070E00026C78ECFF89410926F0010928100109285001092840081E085BF15BE47985D98ED +:2071000028980C94000008952091B2013091B3012F5F3F4F3093B3012093B201932F37FFA8 +:2071200003C08EEF831B982F990F921710F447980895479A08951F920F920FB60F9211246E +:207140002F938F939F93EF93FF9310928500109284008091A8019091A901009741F00197D3 +:207160009093A9018093A801892B09F45D988091AA019091AB01009741F001979093AB0128 +:207180008093AA01892B09F42898E0E0F0E0859194918F5F9F4F49F08091AC019091AD0153 +:2071A00001969093AD018093AC01FF91EF919F918F912F910F900FBE0F901F90189584E0BC +:2071C0008093E9000DC08091E8008B778093E80003C08EB3882351F08091E80082FFF9CFBE +:2071E0008091E80085FFEFCF8091F1000895982F83E08093E9008091E80085FD0DC0809136 +:20720000E8008E778093E80003C08EB3882369F08091E80080FFF9CF9093F1005D9A84E6C9 +:2072200090E09093A9018093A80108954F925F926F927F928F929F92AF92BF92CF92DF921E +:20724000EF92FF920F931F93CF93DF9384E08093E9008091E80082FF57C2289A84E690E065 +:207260009093AB018093AA01AADF182F853481F48CE49DE19093AD018093AC0107B600FC4B +:20728000FDCFF999FECF81E180935700E89503C0843519F494DF8DE00DC28C34E1F38035F9 +:2072A000D1F3843721F484E4A2DF80E003C2813611F489E5FFC18134B1F481DF182F7FDFE3 +:2072C00090E0880F991FAA2797FDA095BA2F312F330F20E0442737FD4095542F822B932B68 +:2072E000A42BB52BB8C1803711F483E5E3C1833549F4C0E0D1E089917ADF21E0C730D20714 +:20730000D1F7D9C1863521F481E371DF80E3D2C1833731F487E86BDF85E969DF8EE1CAC149 +:207320008536B9F4E0E0F0E093E085E090935700E89507B600FCFDCF80935700E89507B65D +:2073400000FCFDCFE058FF4FA0E7E030FA0771F7A2CF823739F4E1E0F0E089E08093570024 +:207360008491A8C1863439F4E0E0F0E089E08093570084919FC18E3439F4E3E0F0E089E0E5 +:2073800080935700849196C1813539F4E2E0F0E089E08093570084918DC1823631F489E521 +:2073A00026DF80E024DF80E885C1823419F0873609F0E5C01092AD011092AC0100DF082FE8 +:2073C000FEDEF82EFCDE682E8554823008F071C1902F80E0CF2DD0E0C82BD92B10926F00B3 +:2073E000173609F04BC081E180935700E895DD24CC24C3943FC0E090AE01F090AF010091CC +:20740000B0011091B101B6E46B16D9F4ED2DF0E0EE29FF29E4918E2FEADEDD2081F082E08D +:2074200090E0A0E0B0E0E80EF91E0A1F1B1FE092AE01F092AF010093B0011093B101DC2470 +:2074400018C0D801C701B695A7959795879559D5CEDE82E090E0A0E0B0E0E80EF91E0A1FF2 +:207460001B1FE092AE01F092AF010093B0011093B1012197209709F0BECF7DC08090AE01F5 +:207480009090AF01A090B001B090B10196E4691609F05DC083E0F40180935700E89507B63E +:2074A00000FCFDCF54C0F6E46F1661F5772031F1E090AE01F090AF010091B0011091B1019E +:2074C0007EDED82ECC24852D90E08C299D29F7010C0140925700E895112482E090E0A0E08B +:2074E000B0E0E80EF91E0A1F1B1FE092AE01F092AF010093B0011093B10102C060DE582E1A +:20750000742423C0E090AE01F090AF010091B0011091B10116950795F794E79450DE682FFA +:20752000C701F7D48091AE019091AF01A091B001B091B1010296A11DB11D8093AE01909349 +:20754000AF01A093B001B093B101219704C05524772444244394209709F0A5CF96E46916B6 +:2075600041F485E0F40180935700E89507B600FCFDCF8DE03CDE82E080936F009CC0833492 +:2075800071F40091AE011091AF0119DE90E021E0F8010C0120935700E89511247CCE8336C8 +:2075A00019F5E090AE01F090AF010091B0011091B10105DEF701E16090E021E00C0120938C +:2075C0005700E895112482E090E0A0E0B0E0E80EF91E0A1F1B1FE092AE01F092AF0100936A +:2075E000B0011093B10157CE8D3661F4E091AE01F091AF0185E080935700E89507B600FCF2 +:20760000FDCF49CE823551F4E091AE01F091AF0105911491812FEBDD802F4CC0843421F5FE +:20762000E090AE01F090AF010091B0011091B10116950795F794E794C2DD682FC70169D4DE +:207640008091AE019091AF01A091B001B091B1010296A11DB11D8093AE019093AF01A093D8 +:20766000B001B093B10117CE843609F5E090AE01F090AF010091B0011091B101D801C70142 +:20768000B695A795979587953CD4B1DD82E090E0A0E0B0E0E80EF91E0A1F1B1FE092AE010A +:2076A000F092AF010093B0011093B10104C08B3111F08FE39CDD83E08093E9009091E8002B +:2076C0008091E8008E778093E80095FF04C010C08EB38823C9F08091E80080FFF9CF809193 +:2076E000E8008E778093E80003C08EB3882361F08091E80080FFF9CF84E08093E9008091F1 +:20770000E8008B778093E800DF91CF911F910F91FF90EF90DF90CF90BF90AF909F908F90AC +:207720007F906F905F904F9008959091B601892F8F77813249F58091B7018032A1F081328A +:2077400019F5913A09F58091E800877F8093E8008DE091E067E070E00BD28091E8008B770B +:207760008093E8000895913279F48091E800877F8093E8008DE091E067E070E05DD2809192 +:20778000E8008E778093E800089582E061EC42E0B5D083E061E842E1B1D084E060E842E1EF +:2077A000ADC084B7877F84BF88E10FB6F89480936000109260000FBE20E880E090E00FB63F +:2077C000F89420936100809361000FBE81E085BF92E095BF3F9A209A559AE1E6F0E02083A1 +:2077E000108247985D982898109289008AEF8093880090936F0083E080938100F0C040911A +:20780000000850910108109201081092000894B714BE88E10FB6F8948093600010926000D5 +:207820000FBE292F30E0F901E270F07091FD18C090FF05C0859194918F5F9F4F81F423FFFF +:207840000FC08091090190910A014817590741F0E0E0F0E0859194918F5F9F4F09F042DC64 +:20786000A0DF78941092AD011092AC010CC0DEDC36D38091AC019091AD0181549F4110F00D +:207880001092140141DC80911401882381F78091E00081608093E00025DC80E090E0089598 +:2078A000FA01923049F0933061F09130F9F485E191E022E130E01EC087E291E02EE330E04D +:2078C00019C0882329F485E691E024E030E012C0813029F489E691E022E230E00BC0823006 +:2078E00029F48DE891E028E130E004C080E090E020E030E091838083C90108958093E9004E +:207900008091EB0081608093EB001092ED006093EC004093ED008091EE00881F8827881F62 +:2079200008958091B60188238CF403C08EB38823B1F08091E80082FFF9CF8091E8008B772A +:207940008093E80008958EB3882349F08091E80080FFF9CF8091E8008E778093E800089594 +:20796000EF92FF920F931F9345D04CD008ED10E0F80180818F77808380818068808380819B +:207980008F7D808319BC1EBA1092B40180EEE82EF12CF70180818B7F8083F8018081816052 +:2079A000808380E060E042E0A9DFE1EEF0E080818E7F8083E2EEF0E0808181608083808144 +:2079C00088608083F70180818E7F8083F8018081806180831F910F91FF90EF900895E7ED06 +:2079E000F0E08081816080838AE482BF81E08093B501B6CFE8EDF0E080818E7F808310921C +:207A0000E20008951092DA001092E10008951F920F920FB60F9211242F933F934F935F93F6 +:207A20006F937F938F939F93AF93BF93EF93FF938091DA0080FF1BC08091D80080FF17C0B2 +:207A40008091DA008E7F8093DA008091D90080FF0BC080E189BD82E189BD09B400FEFDCF36 +:207A600081E08EBB3BD203C019BC1EBA37D28091E10080FF17C08091E20080FF13C0809138 +:207A8000E2008E7F8093E2008091E20080618093E2008091D80080628093D80019BC85E049 +:207AA0008EBB1CD28091E10084FF2CC08091E20084FF28C080E189BD82E189BD09B400FEC5 +:207AC000FDCF8091D8008F7D8093D8008091E1008F7E8093E1008091E2008F7E8093E20012 +:207AE0008091E20081608093E2008091B401882331F48091E30087FD02C081E001C084E067 +:207B00008EBBECD18091E10083FF21C08091E20083FF1DC08091E100877F8093E10082E06A +:207B20008EBB1092B4018091E1008E7F8093E1008091E2008E7F8093E2008091E2008061E9 +:207B40008093E20080E060E042E0D8DEC7D1FF91EF91BF91AF919F918F917F916F915F9130 +:207B60004F913F912F910F900FBE0F901F9018959C014091BC015091BD014617570718F49D +:207B8000F90190E044C06115710511F0AB01F8CF8091E8008E778093E80040E050E0F0CF0F +:207BA0008EB3882309F444C0853009F443C08091E80083FF02C081E008958091E80082FD70 +:207BC00031C08091E80080FF22C08091F3009091F200782F60E0292F30E0262B372B07C07A +:207BE00081918093F100415050402F5F3F4F4115510519F02830310598F390E02830310566 +:207C000009F491E08091E8008E778093E8004115510531F6992321F605C08EB3882341F075 +:207C2000853041F08091E80082FFF7CF80E0089582E0089583E008959C016115710529F47C +:207C40008091E8008B778093E800F90126C08EB3882391F1853091F18091E80083FF02C06C +:207C600081E008958091E80082FFF1CF06C08091F10081936150704059F02091F300809191 +:207C8000F200322F20E090E0822B932B892B79F78091E8008B778093E80061157105B9F601 +:207CA00005C08EB3882341F0853041F08091E80080FFF7CF80E0089582E0089583E00895C2 +:207CC0000F931F93DF93CF9300D0CDB7DEB7E6EBF1E08091F100819381E0EE3BF807C9F792 +:207CE00024DD8091E80083FFE4C08091B6019091B701953009F46DC0963040F4913081F1A7 +:207D0000913070F0933009F0D4C02AC0983009F4A3C0993009F4B2C0963009F0CAC07CC023 +:207D2000803809F4C6C0823809F0C3C08091BA0187708093E9008091EB001092E9002091DB +:207D4000E800277F2093E80090E025E0969587952A95E1F781708093F1001092F10087C0D8 +:207D6000882319F0823009F0A4C08F71823009F0A0C08091B801882331F52091BA01277097 +:207D800009F497C02093E9008091EB0080FF1BC0933021F48091EB00806213C08091EB0018 +:207DA00080618093EB0081E090E002C0880F991F2A95E2F78093EA001092EA008091EB00E5 +:207DC00088608093EB001092E9008091E800877F51C0882309F06DC01091B8011F770FB79B +:207DE000F8948091E800877F8093E8009ADD8091E80080FFFCCF8091E3008078812B809398 +:207E0000E30080688093E300112311F482E001C083E08EBB0FBF4DC08058823008F049C033 +:207E20008091B8019091B9016091BA01AE014F5F5F4F36DDBC01009709F43BC08091E8008E +:207E4000877F8093E80089819A8192DE8091E8008B778093E8002DC0803859F58091E800AA +:207E6000877F8093E8008091B4018093F1008091E8008E778093E80054DD1BC08823C9F4CA +:207E80009091B8019230A8F48091E800877F8093E8009093B40145DD8091B401882331F420 +:207EA0008091E30087FD02C081E001C084E08EBB6CDC8091E80083FF0AC08091EB0080624E +:207EC0008093EB008091E800877F8093E8000F900F90CF91DF911F910F91089508951F9360 +:207EE0008EB3882361F01091E9001092E9008091E80083FF01C0E4DE17701093E9001F916F +:207F00000895F999FECF92BD81BDF89A992780B50895262FF999FECF1FBA92BD81BD20BDBD +:207F20000FB6F894FA9AF99A0FBE01960895F894FFCF4341544552494E4100777700080031 +:207F40000000000000080112011001020000084123370001000201000109023E00020100FE +:207F600080320904000001020201000524001001042402040524060001070582030800FF0C +:207F800009040100020A000000070504021000010705830210000104030904220341007216 +:207FA000006400750069006E006F0020004D006900630072006F0020002000200000001810 +:1A7FC00003410072006400750069006E006F0020004C004C004300000000D7 +:00000001FF diff --git a/Software/ATmega32U4_nl/HackCube.cpp b/Software/ATmega32U4_nl/HackCube.cpp new file mode 100644 index 0000000..2926803 --- /dev/null +++ b/Software/ATmega32U4_nl/HackCube.cpp @@ -0,0 +1,38 @@ +#include "HackCube.h" + +HackCube::Cube(void){ + +}; + +void HackCube::Begin() +{ + +}; + +void HackCube::pinSetup(){ + pinMode(nRF_CS_1, OUTPUT); + pinMode(nRF_CE,OUTPUT); + + pinMode(RF433_CS, OUTPUT); + pinMode(RF433_GDO0,OUTPUT); + pinMode(RF433_GDO2, INPUT); + + digitalWrite(RF433_CS, HIGH); + digitalWrite(RF433_GDO0, LOW); + digitalWrite(RF315_CS, HIGH); + digitalWrite(RF315_GDO0, LOW); + + pinMode(RF315_CS, OUTPUT); + pinMode(RF315_GDO0,OUTPUT); + pinMode(RF315_GDO2, INPUT); + + pinMode(RF_EN, OUTPUT); + digitalWrite(RF_EN, HIGH); + + pinMode(ID_OUT, INPUT); + pinMode(MOD, OUTPUT); + pinMode(SHD, OUTPUT); + + digitalWrite(MOD,LOW); + digitalWrite(SHD,LOW); +}; diff --git a/Software/ATmega32U4_nl/HackCube.h b/Software/ATmega32U4_nl/HackCube.h new file mode 100644 index 0000000..7e7e18e --- /dev/null +++ b/Software/ATmega32U4_nl/HackCube.h @@ -0,0 +1,23 @@ +#include "Arduino.h" + + +#ifndef HackCube_H +#define HackCube_H + +#include "Pin.h" + +class HackCube{ + +public: + Cube(void); + // Initialisatie module + void Begin(); + // Stel module io in op de overeenkomstige invoer- en uitvoermodus + void pinSetup(); + +private: + int pin; + +}; + +#endif diff --git a/Software/ATmega32U4_nl/HackRadio.cpp b/Software/ATmega32U4_nl/HackRadio.cpp new file mode 100644 index 0000000..e87c85c --- /dev/null +++ b/Software/ATmega32U4_nl/HackRadio.cpp @@ -0,0 +1,350 @@ +#include "HackRadio.h" +#include + +//#if defined(__AVR_ATmega1280__) + +//#if defined (MCU_STM32F103R) +#if defined(__STM32F1__) +#include "itoa.h" +#endif +// + + + +unsigned long HackRadio::nReceivedValue = NULL; +String HackRadio::nsn; +String HackRadio::nkey; +String HackRadio::action; +unsigned int HackRadio::nReceivedBitlength = 0; +unsigned int HackRadio::nReceivedDelay = 0; +unsigned int HackRadio::nReceivedProtocol = 0; +int HackRadio::nReceiveTolerance = 60; +unsigned int HackRadio::timings[HackRadio_MAX_CHANGES]; + + +HackRadio::HackRadio() { + this->nTransmitterPin = -1; + this->setPulseLength(100);//lengte + this->setRepeatTransmit(4);//Aantal keren + this->setProtocol(1);//methode + + this->nReceiverInterrupt = -1; + this->setReceiveTolerance(60); + HackRadio::nReceivedValue = NULL; + +} + + +void HackRadio::Begin(void){ + +}; + + + + + +String HackRadio::getsn() { + return HackRadio::nsn; +} +String HackRadio::getkey() { + return HackRadio::nkey; +} +String HackRadio::getaction() { + return HackRadio::action; +} + + +void HackRadio::enableTransmit(int nTransmitterPin) { + this->nTransmitterPin = nTransmitterPin; + pinMode(this->nTransmitterPin, OUTPUT); +} + + + +void HackRadio::sendPreamble() { + this->transmit(360,389);//435 +} + +void HackRadio::transmit(int nHighPulses, int nLowPulses) { + digitalWrite(this->nTransmitterPin, HIGH); + delayMicroseconds( nHighPulses); + digitalWrite(this->nTransmitterPin, LOW); + delayMicroseconds( nLowPulses); +} + + +void HackRadio::Send0() { + + this->transmit(721,390);//690 420 + //Serial.print("0"); +} +void HackRadio::Send1() { + this->transmit(371,756);//815 + //Serial.print("1"); +} + + +void HackRadio::Send(unsigned long data,unsigned long sn,int action,int Repeat){ + for (int nRepeat=0; nRepeatsendPreamble(); + } + this->transmit(360,3769);//202 + + for (int i = 0; i < 32; i++) { + if ((data >> i)&1) + this->Send1(); + else + this->Send0(); + } + + for (int i = 0; i < 28; i++) { + if ((sn >> i)&1) + this->Send1(); + else + this->Send0(); + } + + for (int i = 0; i < 5; i++) { + if ((action >> i)&1) + this->Send1(); + else + this->Send0(); + } + + this->transmit(300,15400);//202 + + } +} + + + +bool HackRadio::available() { + return HackRadio::nReceivedValue != NULL; +} + +void HackRadio::resetAvailable() { + HackRadio::nReceivedValue = NULL; +} + + +void HackRadio::setProtocol(int nProtocol) { + this->nProtocol = nProtocol; + if (nProtocol == 1){ + this->setPulseLength(245); + } + else if (nProtocol == 2) { + this->setPulseLength(650); + } + else if (nProtocol == 3) { + this->setPulseLength(100); + } +} + +void HackRadio::setProtocol(int nProtocol, int nPulseLength) { + this->nProtocol = nProtocol; + this->setPulseLength(nPulseLength); +} + +void HackRadio::setPulseLength(int nPulseLength) { + this->nPulseLength = nPulseLength; +} + +void HackRadio::setRepeatTransmit(int nRepeatTransmit) { + this->nRepeatTransmit = nRepeatTransmit; +} + +void HackRadio::setReceiveTolerance(int nPercent) { + HackRadio::nReceiveTolerance = nPercent; +} + + +void HackRadio::enableReceive(int interrupt) { + this->nReceiverInterrupt = interrupt; + this->enableReceive(); +} + + +void HackRadio::enableReceive() { + if (this->nReceiverInterrupt != -1) { + HackRadio::nReceivedValue = NULL; + HackRadio::nReceivedBitlength = NULL; + HackRadio::nsn; + HackRadio::nkey; + HackRadio::action; + attachInterrupt(this->nReceiverInterrupt, handleInterrupt, CHANGE); + } +} + + +void HackRadio::handleInterrupt() { + + static unsigned int duration; + static unsigned int changeCount; + static unsigned long lastTime; + static unsigned int repeatCount; + + long time = micros(); + duration = time - lastTime; + + if ( + changeCount > 155 + && duration > HackRadio::timings[0] - 4000 + && duration < HackRadio::timings[0] + 4000 + && HackRadio::timings[24]<4500 + && HackRadio::timings[24]>3500 + ) { + //Serial.println(changeCount); + receiveProtocol2(changeCount); + HackRadio::nReceivedValue = 1; + changeCount = 0; + } else if (duration > 13000) { + changeCount = 0; + } + + + + if (changeCount >= HackRadio_MAX_CHANGES) { + changeCount = 0; + repeatCount = 0; + } + HackRadio::timings[changeCount++] = duration; + lastTime = time; +} + +bool HackRadio::receiveProtocol2(unsigned int changeCount){ + String sn; + String tiaoma; + String action; + unsigned long delay = HackRadio::timings[0] / 31; + unsigned long delayTolerance = delay * HackRadio::nReceiveTolerance * 0.01; + for (int i = 25 ; i< 89 ; i=i+2){ + if (HackRadio::timings[i] < HackRadio::timings[i+1]){ + tiaoma +="0"; + } else if (HackRadio::timings[i] > HackRadio::timings[i+1]) { + tiaoma +="1"; + } + } + for (int i = 89 ; i< 145 ; i=i+2) { + if (HackRadio::timings[i] < HackRadio::timings[i+1]) { + sn +="0"; + } else if (HackRadio::timings[i] > HackRadio::timings[i+1]) { + sn +="1"; + } + } + for (int i=145;i<153;i=i+2){ + if (HackRadio::timings[i] < HackRadio::timings[i+1]) { + action +="0"; + } else if (HackRadio::timings[i] > HackRadio::timings[i+1]) { + action +="1"; + } + } + HackRadio::action =dec4bin(action); + HackRadio::nkey =dec4bin(tiaoma); + HackRadio::nsn =dec4bin(sn); + HackRadio::nReceivedValue = 1; + HackRadio::nReceivedProtocol = 4; + if (tiaoma == 0){ + return false; + }else if (tiaoma != 0){ + return true; + } +} + +//因为 编译 链路  不通 +/* +String HackRadio::dec4bin(String data){ +String ss; +int len = data.length(); +String sss; +//data.copy(datas,len,0); +//cout<=0;i--){ + sss = data[i]; + if(sss=="0"){ + ss += "1"; + }else if(sss=="1"){ + ss += "0"; + } + } + unsigned long dataa=strtoul(ss.c_str(),NULL,2); + char string[64]; + ultoa(dataa, string, 16); + return string; + }else if(len==32){ + for (int i=31;i>=0;i--){ + sss = data[i]; + if(sss=="0"){ + ss += "1"; + }else if(sss=="1"){ + ss += "0"; + } + } + unsigned long dataa=strtoul(ss.c_str(),NULL,2); + char string[64]; + ultoa(dataa, string, 16); + return string; + }else if(len==4){ + for (int i=3;i>=0;i--){ + sss = data[i]; + if(sss=="0"){ + ss += "1"; + }else if(sss=="1"){ + ss += "0"; + } + } + unsigned long dataa=strtoul(ss.c_str(),NULL,2); + char string[64]; + ultoa(dataa, string, 16); + return string; + } +}*/ +String HackRadio::dec4bin(String data){ +String ss; +int len = data.length(); +String sss; +//data.copy(datas,len,0); +//cout<=0;i--){ + sss = String(data[i]); + if(sss=="0"){ + ss += "1"; + }else if(sss=="1"){ + ss += "0"; + } + } + unsigned long dataa=strtoul(ss.c_str(),NULL,2); + char string[64]; + ultoa(dataa, string, 16); + return string; + }else if(len==32){ + for (int i=31;i>=0;i--){ + sss =String(data[i]); + if(sss=="0"){ + ss += "1"; + }else if(sss=="1"){ + ss += "0"; + } + } + unsigned long dataa=strtoul(ss.c_str(),NULL,2); + char string[64]; + ultoa(dataa, string, 16); + return string; + }else if(len==4){ + for (int i=3;i>=0;i--){ + sss = String(data[i]); + if(sss=="0"){ + ss += "1"; + }else if(sss=="1"){ + ss += "0"; + } + } + unsigned long dataa=strtoul(ss.c_str(),NULL,2); + char string[64]; + ultoa(dataa, string, 16); + return string; + } +} diff --git a/Software/ATmega32U4_nl/HackRadio.h b/Software/ATmega32U4_nl/HackRadio.h new file mode 100644 index 0000000..b7bd3da --- /dev/null +++ b/Software/ATmega32U4_nl/HackRadio.h @@ -0,0 +1,67 @@ +//#include "Pin.h" +#include "Arduino.h" + +#ifndef HackRadio_H +#define HackRadio_H + + +#define HackRadio_MAX_CHANGES 200//67 + +#define PROTOCOL3_SYNC_FACTOR 71 +#define PROTOCOL3_0_HIGH_CYCLES 4 +#define PROTOCOL3_0_LOW_CYCLES 11 +#define PROTOCOL3_1_HIGH_CYCLES 9 +#define PROTOCOL3_1_LOW_CYCLES 6 + +class HackRadio{ +public: + int nReceiverInterrupt; + int nTransmitterPin; + int nPulseLength; + int nRepeatTransmit; + char nProtocol; + + static String nkey; + static String nsn; + static String action; + static int nReceiveTolerance; + static unsigned long nReceivedValue; + static unsigned int nReceivedBitlength; + static unsigned int nReceivedDelay; + static unsigned int nReceivedProtocol; + static unsigned int timings[HackRadio_MAX_CHANGES]; + + HackRadio(); + void Begin(); + void setPulseLength(int nPulseLength); + void setProtocol(int nProtocol); + void setProtocol(int nProtocol, int nPulseLength); + void setRepeatTransmit(int nRepeatTransmit); + void enableTransmit(int nTransmitterPin); + void setReceiveTolerance(int nPercent); + void enableReceive(int interrupt); + void enableReceive(); + + static void handleInterrupt(); + static bool receiveProtocol2(unsigned int changeCount); + static String dec4bin(String data); + String getkey(); + String getsn(); + String getaction(); + + bool available(); + void resetAvailable(); + + void sendPreamble(); + void transmit(int nHighPulses, int nLowPulses); + void Send0(); + void Send1(); + void Send(unsigned long data,unsigned long sn,int action,int Repeat=4); + +; +private: + + +}; + +#endif diff --git a/Software/ATmega32U4_nl/Pin.h b/Software/ATmega32U4_nl/Pin.h new file mode 100644 index 0000000..5c09963 --- /dev/null +++ b/Software/ATmega32U4_nl/Pin.h @@ -0,0 +1,31 @@ +#ifndef Pin_H +#define Pin_H + +#define LED 6 + +#define nRF_CS_1 A0 +#define nRF_CE A1 +#define nRF_IRQ 7 + +#define RF433_CS A3 //RF_CS2 +#define RF433_GDO0 A2 +#define RF433_GDO2 2 +#define RF433_att 1 + +#define RF315_CS A3 //RF_CS2 +#define RF315_GDO0 A2 +#define RF315_GDO2 2 +#define RF315_att 1 + +#define ID_OUT 5 +#define MOD 6 +#define SHD 9 + +#define RF_EN 8 + +#define PN532_CS +#define PN532_IRQ + + + +#endif diff --git a/Software/ATmega32U4_nl/RCSwitch.cpp b/Software/ATmega32U4_nl/RCSwitch.cpp new file mode 100644 index 0000000..1a6736e --- /dev/null +++ b/Software/ATmega32U4_nl/RCSwitch.cpp @@ -0,0 +1,701 @@ +/* + RCSwitch - Arduino libary for remote control outlet switches + Copyright (c) 2011 Suat Özgür. All right reserved. + + Contributors: + - Andre Koehler / info(at)tomate-online(dot)de + - Gordeev Andrey Vladimirovich / gordeev(at)openpyro(dot)com + - Skineffect / http://forum.ardumote.com/viewtopic.php?f=2&t=46 + - Dominik Fischer / dom_fischer(at)web(dot)de + - Frank Oltmanns / .(at)gmail(dot)com + - Andreas Steinel / A.(at)gmail(dot)com + - Max Horn / max(at)quendi(dot)de + - Robert ter Vehn / .(at)gmail(dot)com + - Johann Richard / .(at)gmail(dot)com + - Vlad Gheorghe / .(at)gmail(dot)com https://github.com/vgheo + + Project home: https://github.com/sui77/rc-switch/ + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "RCSwitch.h" + +#ifdef RaspberryPi + // PROGMEM and _P functions are for AVR based microprocessors, + // so we must normalize these for the ARM processor: + #define PROGMEM + #define memcpy_P(dest, src, num) memcpy((dest), (src), (num)) +#endif + +#if defined(ESP8266) || defined(ESP32) + // interrupt handler and related code must be in RAM on ESP8266, + // according to issue #46. + #define RECEIVE_ATTR ICACHE_RAM_ATTR +#else + #define RECEIVE_ATTR +#endif + + +/* Format for protocol definitions: + * {pulselength, Sync bit, "0" bit, "1" bit} + * + * pulselength: pulse length in microseconds, e.g. 350 + * Sync bit: {1, 31} means 1 high pulse and 31 low pulses + * (perceived as a 31*pulselength long pulse, total length of sync bit is + * 32*pulselength microseconds), i.e: + * _ + * | |_______________________________ (don't count the vertical bars) + * "0" bit: waveform for a data bit of value "0", {1, 3} means 1 high pulse + * and 3 low pulses, total length (1+3)*pulselength, i.e: + * _ + * | |___ + * "1" bit: waveform for a data bit of value "1", e.g. {3,1}: + * ___ + * | |_ + * + * These are combined to form Tri-State bits when sending or receiving codes. + */ +#if defined(ESP8266) || defined(ESP32) +static const RCSwitch::Protocol proto[] = { +#else +static const RCSwitch::Protocol PROGMEM proto[] = { +#endif + { 350, { 1, 31 }, { 1, 3 }, { 3, 1 }, false }, // protocol 1 + { 650, { 1, 10 }, { 1, 2 }, { 2, 1 }, false }, // protocol 2 + { 100, { 30, 71 }, { 4, 11 }, { 9, 6 }, false }, // protocol 3 + { 380, { 1, 6 }, { 1, 3 }, { 3, 1 }, false }, // protocol 4 + { 500, { 6, 14 }, { 1, 2 }, { 2, 1 }, false }, // protocol 5 + { 450, { 23, 1 }, { 1, 2 }, { 2, 1 }, true }, // protocol 6 (HT6P20B) + { 150, { 2, 62 }, { 1, 6 }, { 6, 1 }, false } // protocol 7 (HS2303-PT, i. e. used in AUKEY Remote) +}; + +enum { + numProto = sizeof(proto) / sizeof(proto[0]) +}; + +#if not defined( RCSwitchDisableReceiving ) +volatile unsigned long RCSwitch::nReceivedValue = 0; +volatile unsigned int RCSwitch::nReceivedBitlength = 0; +volatile unsigned int RCSwitch::nReceivedDelay = 0; +volatile unsigned int RCSwitch::nReceivedProtocol = 0; +int RCSwitch::nReceiveTolerance = 60; +const unsigned int RCSwitch::nSeparationLimit = 4300; +// separationLimit: minimum microseconds between received codes, closer codes are ignored. +// according to discussion on issue #14 it might be more suitable to set the separation +// limit to the same time as the 'low' part of the sync signal for the current protocol. +unsigned int RCSwitch::timings[RCSWITCH_MAX_CHANGES]; +#endif + +RCSwitch::RCSwitch() { + this->nTransmitterPin = -1; + this->setRepeatTransmit(10); + this->setProtocol(1); + #if not defined( RCSwitchDisableReceiving ) + this->nReceiverInterrupt = -1; + this->setReceiveTolerance(60); + RCSwitch::nReceivedValue = 0; + #endif +} + +/** + * Sets the protocol to send. + */ +void RCSwitch::setProtocol(Protocol protocol) { + this->protocol = protocol; +} + +/** + * Sets the protocol to send, from a list of predefined protocols + */ +void RCSwitch::setProtocol(int nProtocol) { + if (nProtocol < 1 || nProtocol > numProto) { + nProtocol = 1; // TODO: trigger an error, e.g. "bad protocol" ??? + } +#if defined(ESP8266) || defined(ESP32) + this->protocol = proto[nProtocol-1]; +#else + memcpy_P(&this->protocol, &proto[nProtocol-1], sizeof(Protocol)); +#endif +} + +/** + * Sets the protocol to send with pulse length in microseconds. + */ +void RCSwitch::setProtocol(int nProtocol, int nPulseLength) { + setProtocol(nProtocol); + this->setPulseLength(nPulseLength); +} + + +/** + * Sets pulse length in microseconds + */ +void RCSwitch::setPulseLength(int nPulseLength) { + this->protocol.pulseLength = nPulseLength; +} + +/** + * Sets Repeat Transmits + */ +void RCSwitch::setRepeatTransmit(int nRepeatTransmit) { + this->nRepeatTransmit = nRepeatTransmit; +} + +/** + * Set Receiving Tolerance + */ +#if not defined( RCSwitchDisableReceiving ) +void RCSwitch::setReceiveTolerance(int nPercent) { + RCSwitch::nReceiveTolerance = nPercent; +} +#endif + + +/** + * Enable transmissions + * + * @param nTransmitterPin Arduino Pin to which the sender is connected to + */ +void RCSwitch::enableTransmit(int nTransmitterPin) { + this->nTransmitterPin = nTransmitterPin; + pinMode(this->nTransmitterPin, OUTPUT); +} + +/** + * Disable transmissions + */ +void RCSwitch::disableTransmit() { + this->nTransmitterPin = -1; +} + +/** + * Switch a remote switch on (Type D REV) + * + * @param sGroup Code of the switch group (A,B,C,D) + * @param nDevice Number of the switch itself (1..3) + */ +void RCSwitch::switchOn(char sGroup, int nDevice) { + this->sendTriState( this->getCodeWordD(sGroup, nDevice, true) ); +} + +/** + * Switch a remote switch off (Type D REV) + * + * @param sGroup Code of the switch group (A,B,C,D) + * @param nDevice Number of the switch itself (1..3) + */ +void RCSwitch::switchOff(char sGroup, int nDevice) { + this->sendTriState( this->getCodeWordD(sGroup, nDevice, false) ); +} + +/** + * Switch a remote switch on (Type C Intertechno) + * + * @param sFamily Familycode (a..f) + * @param nGroup Number of group (1..4) + * @param nDevice Number of device (1..4) + */ +void RCSwitch::switchOn(char sFamily, int nGroup, int nDevice) { + this->sendTriState( this->getCodeWordC(sFamily, nGroup, nDevice, true) ); +} + +/** + * Switch a remote switch off (Type C Intertechno) + * + * @param sFamily Familycode (a..f) + * @param nGroup Number of group (1..4) + * @param nDevice Number of device (1..4) + */ +void RCSwitch::switchOff(char sFamily, int nGroup, int nDevice) { + this->sendTriState( this->getCodeWordC(sFamily, nGroup, nDevice, false) ); +} + +/** + * Switch a remote switch on (Type B with two rotary/sliding switches) + * + * @param nAddressCode Number of the switch group (1..4) + * @param nChannelCode Number of the switch itself (1..4) + */ +void RCSwitch::switchOn(int nAddressCode, int nChannelCode) { + this->sendTriState( this->getCodeWordB(nAddressCode, nChannelCode, true) ); +} + +/** + * Switch a remote switch off (Type B with two rotary/sliding switches) + * + * @param nAddressCode Number of the switch group (1..4) + * @param nChannelCode Number of the switch itself (1..4) + */ +void RCSwitch::switchOff(int nAddressCode, int nChannelCode) { + this->sendTriState( this->getCodeWordB(nAddressCode, nChannelCode, false) ); +} + +/** + * Deprecated, use switchOn(const char* sGroup, const char* sDevice) instead! + * Switch a remote switch on (Type A with 10 pole DIP switches) + * + * @param sGroup Code of the switch group (refers to DIP switches 1..5 where "1" = on and "0" = off, if all DIP switches are on it's "11111") + * @param nChannelCode Number of the switch itself (1..5) + */ +void RCSwitch::switchOn(const char* sGroup, int nChannel) { + const char* code[6] = { "00000", "10000", "01000", "00100", "00010", "00001" }; + this->switchOn(sGroup, code[nChannel]); +} + +/** + * Deprecated, use switchOff(const char* sGroup, const char* sDevice) instead! + * Switch a remote switch off (Type A with 10 pole DIP switches) + * + * @param sGroup Code of the switch group (refers to DIP switches 1..5 where "1" = on and "0" = off, if all DIP switches are on it's "11111") + * @param nChannelCode Number of the switch itself (1..5) + */ +void RCSwitch::switchOff(const char* sGroup, int nChannel) { + const char* code[6] = { "00000", "10000", "01000", "00100", "00010", "00001" }; + this->switchOff(sGroup, code[nChannel]); +} + +/** + * Switch a remote switch on (Type A with 10 pole DIP switches) + * + * @param sGroup Code of the switch group (refers to DIP switches 1..5 where "1" = on and "0" = off, if all DIP switches are on it's "11111") + * @param sDevice Code of the switch device (refers to DIP switches 6..10 (A..E) where "1" = on and "0" = off, if all DIP switches are on it's "11111") + */ +void RCSwitch::switchOn(const char* sGroup, const char* sDevice) { + this->sendTriState( this->getCodeWordA(sGroup, sDevice, true) ); +} + +/** + * Switch a remote switch off (Type A with 10 pole DIP switches) + * + * @param sGroup Code of the switch group (refers to DIP switches 1..5 where "1" = on and "0" = off, if all DIP switches are on it's "11111") + * @param sDevice Code of the switch device (refers to DIP switches 6..10 (A..E) where "1" = on and "0" = off, if all DIP switches are on it's "11111") + */ +void RCSwitch::switchOff(const char* sGroup, const char* sDevice) { + this->sendTriState( this->getCodeWordA(sGroup, sDevice, false) ); +} + + +/** + * Returns a char[13], representing the code word to be send. + * + */ +char* RCSwitch::getCodeWordA(const char* sGroup, const char* sDevice, bool bStatus) { + static char sReturn[13]; + int nReturnPos = 0; + + for (int i = 0; i < 5; i++) { + sReturn[nReturnPos++] = (sGroup[i] == '0') ? 'F' : '0'; + } + + for (int i = 0; i < 5; i++) { + sReturn[nReturnPos++] = (sDevice[i] == '0') ? 'F' : '0'; + } + + sReturn[nReturnPos++] = bStatus ? '0' : 'F'; + sReturn[nReturnPos++] = bStatus ? 'F' : '0'; + + sReturn[nReturnPos] = '\0'; + return sReturn; +} + +/** + * Encoding for type B switches with two rotary/sliding switches. + * + * The code word is a tristate word and with following bit pattern: + * + * +-----------------------------+-----------------------------+----------+------------+ + * | 4 bits address | 4 bits address | 3 bits | 1 bit | + * | switch group | switch number | not used | on / off | + * | 1=0FFF 2=F0FF 3=FF0F 4=FFF0 | 1=0FFF 2=F0FF 3=FF0F 4=FFF0 | FFF | on=F off=0 | + * +-----------------------------+-----------------------------+----------+------------+ + * + * @param nAddressCode Number of the switch group (1..4) + * @param nChannelCode Number of the switch itself (1..4) + * @param bStatus Whether to switch on (true) or off (false) + * + * @return char[13], representing a tristate code word of length 12 + */ +char* RCSwitch::getCodeWordB(int nAddressCode, int nChannelCode, bool bStatus) { + static char sReturn[13]; + int nReturnPos = 0; + + if (nAddressCode < 1 || nAddressCode > 4 || nChannelCode < 1 || nChannelCode > 4) { + return 0; + } + + for (int i = 1; i <= 4; i++) { + sReturn[nReturnPos++] = (nAddressCode == i) ? '0' : 'F'; + } + + for (int i = 1; i <= 4; i++) { + sReturn[nReturnPos++] = (nChannelCode == i) ? '0' : 'F'; + } + + sReturn[nReturnPos++] = 'F'; + sReturn[nReturnPos++] = 'F'; + sReturn[nReturnPos++] = 'F'; + + sReturn[nReturnPos++] = bStatus ? 'F' : '0'; + + sReturn[nReturnPos] = '\0'; + return sReturn; +} + +/** + * Like getCodeWord (Type C = Intertechno) + */ +char* RCSwitch::getCodeWordC(char sFamily, int nGroup, int nDevice, bool bStatus) { + static char sReturn[13]; + int nReturnPos = 0; + + int nFamily = (int)sFamily - 'a'; + if ( nFamily < 0 || nFamily > 15 || nGroup < 1 || nGroup > 4 || nDevice < 1 || nDevice > 4) { + return 0; + } + + // encode the family into four bits + sReturn[nReturnPos++] = (nFamily & 1) ? 'F' : '0'; + sReturn[nReturnPos++] = (nFamily & 2) ? 'F' : '0'; + sReturn[nReturnPos++] = (nFamily & 4) ? 'F' : '0'; + sReturn[nReturnPos++] = (nFamily & 8) ? 'F' : '0'; + + // encode the device and group + sReturn[nReturnPos++] = ((nDevice-1) & 1) ? 'F' : '0'; + sReturn[nReturnPos++] = ((nDevice-1) & 2) ? 'F' : '0'; + sReturn[nReturnPos++] = ((nGroup-1) & 1) ? 'F' : '0'; + sReturn[nReturnPos++] = ((nGroup-1) & 2) ? 'F' : '0'; + + // encode the status code + sReturn[nReturnPos++] = '0'; + sReturn[nReturnPos++] = 'F'; + sReturn[nReturnPos++] = 'F'; + sReturn[nReturnPos++] = bStatus ? 'F' : '0'; + + sReturn[nReturnPos] = '\0'; + return sReturn; +} + +/** + * Encoding for the REV Switch Type + * + * The code word is a tristate word and with following bit pattern: + * + * +-----------------------------+-------------------+----------+--------------+ + * | 4 bits address | 3 bits address | 3 bits | 2 bits | + * | switch group | device number | not used | on / off | + * | A=1FFF B=F1FF C=FF1F D=FFF1 | 1=0FF 2=F0F 3=FF0 | 000 | on=10 off=01 | + * +-----------------------------+-------------------+----------+--------------+ + * + * Source: http://www.the-intruder.net/funksteckdosen-von-rev-uber-arduino-ansteuern/ + * + * @param sGroup Name of the switch group (A..D, resp. a..d) + * @param nDevice Number of the switch itself (1..3) + * @param bStatus Whether to switch on (true) or off (false) + * + * @return char[13], representing a tristate code word of length 12 + */ +char* RCSwitch::getCodeWordD(char sGroup, int nDevice, bool bStatus) { + static char sReturn[13]; + int nReturnPos = 0; + + // sGroup must be one of the letters in "abcdABCD" + int nGroup = (sGroup >= 'a') ? (int)sGroup - 'a' : (int)sGroup - 'A'; + if ( nGroup < 0 || nGroup > 3 || nDevice < 1 || nDevice > 3) { + return 0; + } + + for (int i = 0; i < 4; i++) { + sReturn[nReturnPos++] = (nGroup == i) ? '1' : 'F'; + } + + for (int i = 1; i <= 3; i++) { + sReturn[nReturnPos++] = (nDevice == i) ? '1' : 'F'; + } + + sReturn[nReturnPos++] = '0'; + sReturn[nReturnPos++] = '0'; + sReturn[nReturnPos++] = '0'; + + sReturn[nReturnPos++] = bStatus ? '1' : '0'; + sReturn[nReturnPos++] = bStatus ? '0' : '1'; + + sReturn[nReturnPos] = '\0'; + return sReturn; +} + +/** + * @param sCodeWord a tristate code word consisting of the letter 0, 1, F + */ +void RCSwitch::sendTriState(const char* sCodeWord) { + // turn the tristate code word into the corresponding bit pattern, then send it + unsigned long code = 0; + unsigned int length = 0; + for (const char* p = sCodeWord; *p; p++) { + code <<= 2L; + switch (*p) { + case '0': + // bit pattern 00 + break; + case 'F': + // bit pattern 01 + code |= 1L; + break; + case '1': + // bit pattern 11 + code |= 3L; + break; + } + length += 2; + } + this->send(code, length); +} + +/** + * @param sCodeWord a binary code word consisting of the letter 0, 1 + */ +void RCSwitch::send(const char* sCodeWord) { + // turn the tristate code word into the corresponding bit pattern, then send it + unsigned long code = 0; + unsigned int length = 0; + for (const char* p = sCodeWord; *p; p++) { + code <<= 1L; + if (*p != '0') + code |= 1L; + length++; + } + this->send(code, length); +} + +/** + * Transmit the first 'length' bits of the integer 'code'. The + * bits are sent from MSB to LSB, i.e., first the bit at position length-1, + * then the bit at position length-2, and so on, till finally the bit at position 0. + */ +void RCSwitch::send(unsigned long code, unsigned int length) { + if (this->nTransmitterPin == -1) + return; + +#if not defined( RCSwitchDisableReceiving ) + // make sure the receiver is disabled while we transmit + int nReceiverInterrupt_backup = nReceiverInterrupt; + if (nReceiverInterrupt_backup != -1) { + this->disableReceive(); + } +#endif + + for (int nRepeat = 0; nRepeat < nRepeatTransmit; nRepeat++) { + for (int i = length-1; i >= 0; i--) { + if (code & (1L << i)) + this->transmit(protocol.one); + else + this->transmit(protocol.zero); + } + this->transmit(protocol.syncFactor); + } + + // Disable transmit after sending (i.e., for inverted protocols) + digitalWrite(this->nTransmitterPin, LOW); + +#if not defined( RCSwitchDisableReceiving ) + // enable receiver again if we just disabled it + if (nReceiverInterrupt_backup != -1) { + this->enableReceive(nReceiverInterrupt_backup); + } +#endif +} + +/** + * Transmit a single high-low pulse. + */ +void RCSwitch::transmit(HighLow pulses) { + uint8_t firstLogicLevel = (this->protocol.invertedSignal) ? LOW : HIGH; + uint8_t secondLogicLevel = (this->protocol.invertedSignal) ? HIGH : LOW; + + digitalWrite(this->nTransmitterPin, firstLogicLevel); + delayMicroseconds( this->protocol.pulseLength * pulses.high); + digitalWrite(this->nTransmitterPin, secondLogicLevel); + delayMicroseconds( this->protocol.pulseLength * pulses.low); +} + + +#if not defined( RCSwitchDisableReceiving ) +/** + * Enable receiving data + */ +void RCSwitch::enableReceive(int interrupt) { + this->nReceiverInterrupt = interrupt; + this->enableReceive(); +} + +void RCSwitch::enableReceive() { + if (this->nReceiverInterrupt != -1) { + RCSwitch::nReceivedValue = 0; + RCSwitch::nReceivedBitlength = 0; +#if defined(RaspberryPi) // Raspberry Pi + wiringPiISR(this->nReceiverInterrupt, INT_EDGE_BOTH, &handleInterrupt); +#else // Arduino + attachInterrupt(this->nReceiverInterrupt, handleInterrupt, CHANGE); +#endif + } +} + +/** + * Disable receiving data + */ +void RCSwitch::disableReceive() { +#if not defined(RaspberryPi) // Arduino + detachInterrupt(this->nReceiverInterrupt); +#endif // For Raspberry Pi (wiringPi) you can't unregister the ISR + this->nReceiverInterrupt = -1; +} + +bool RCSwitch::available() { + return RCSwitch::nReceivedValue != 0; +} + +void RCSwitch::resetAvailable() { + RCSwitch::nReceivedValue = 0; +} + +unsigned long RCSwitch::getReceivedValue() { + return RCSwitch::nReceivedValue; +} + +unsigned int RCSwitch::getReceivedBitlength() { + return RCSwitch::nReceivedBitlength; +} + +unsigned int RCSwitch::getReceivedDelay() { + return RCSwitch::nReceivedDelay; +} + +unsigned int RCSwitch::getReceivedProtocol() { + return RCSwitch::nReceivedProtocol; +} + +unsigned int* RCSwitch::getReceivedRawdata() { + return RCSwitch::timings; +} + +/* helper function for the receiveProtocol method */ +static inline unsigned int diff(int A, int B) { + return abs(A - B); +} + +/** + * + */ +bool RECEIVE_ATTR RCSwitch::receiveProtocol(const int p, unsigned int changeCount) { +#if defined(ESP8266) || defined(ESP32) + const Protocol &pro = proto[p-1]; +#else + Protocol pro; + memcpy_P(&pro, &proto[p-1], sizeof(Protocol)); +#endif + + unsigned long code = 0; + //Assuming the longer pulse length is the pulse captured in timings[0] + const unsigned int syncLengthInPulses = ((pro.syncFactor.low) > (pro.syncFactor.high)) ? (pro.syncFactor.low) : (pro.syncFactor.high); + const unsigned int delay = RCSwitch::timings[0] / syncLengthInPulses; + const unsigned int delayTolerance = delay * RCSwitch::nReceiveTolerance / 100; + + /* For protocols that start low, the sync period looks like + * _________ + * _____________| |XXXXXXXXXXXX| + * + * |--1st dur--|-2nd dur-|-Start data-| + * + * The 3rd saved duration starts the data. + * + * For protocols that start high, the sync period looks like + * + * ______________ + * | |____________|XXXXXXXXXXXXX| + * + * |-filtered out-|--1st dur--|--Start data--| + * + * The 2nd saved duration starts the data + */ + const unsigned int firstDataTiming = (pro.invertedSignal) ? (2) : (1); + + for (unsigned int i = firstDataTiming; i < changeCount - 1; i += 2) { + code <<= 1; + if (diff(RCSwitch::timings[i], delay * pro.zero.high) < delayTolerance && + diff(RCSwitch::timings[i + 1], delay * pro.zero.low) < delayTolerance) { + // zero + } else if (diff(RCSwitch::timings[i], delay * pro.one.high) < delayTolerance && + diff(RCSwitch::timings[i + 1], delay * pro.one.low) < delayTolerance) { + // one + code |= 1; + } else { + // Failed + return false; + } + } + + if (changeCount > 7) { // ignore very short transmissions: no device sends them, so this must be noise + RCSwitch::nReceivedValue = code; + RCSwitch::nReceivedBitlength = (changeCount - 1) / 2; + RCSwitch::nReceivedDelay = delay; + RCSwitch::nReceivedProtocol = p; + return true; + } + + return false; +} + +void RECEIVE_ATTR RCSwitch::handleInterrupt() { + + static unsigned int changeCount = 0; + static unsigned long lastTime = 0; + static unsigned int repeatCount = 0; + + const long time = micros(); + const unsigned int duration = time - lastTime; + + if (duration > RCSwitch::nSeparationLimit) { + // A long stretch without signal level change occurred. This could + // be the gap between two transmission. + if (diff(duration, RCSwitch::timings[0]) < 200) { + // This long signal is close in length to the long signal which + // started the previously recorded timings; this suggests that + // it may indeed by a a gap between two transmissions (we assume + // here that a sender will send the signal multiple times, + // with roughly the same gap between them). + repeatCount++; + if (repeatCount == 2) { + for(unsigned int i = 1; i <= numProto; i++) { + if (receiveProtocol(i, changeCount)) { + // receive succeeded for protocol i + break; + } + } + repeatCount = 0; + } + } + changeCount = 0; + } + + // detect overflow + if (changeCount >= RCSWITCH_MAX_CHANGES) { + changeCount = 0; + repeatCount = 0; + } + + RCSwitch::timings[changeCount++] = duration; + lastTime = time; +} +#endif diff --git a/Software/ATmega32U4_nl/RCSwitch.h b/Software/ATmega32U4_nl/RCSwitch.h new file mode 100644 index 0000000..b7755e0 --- /dev/null +++ b/Software/ATmega32U4_nl/RCSwitch.h @@ -0,0 +1,184 @@ +/* + RCSwitch - Arduino libary for remote control outlet switches + Copyright (c) 2011 Suat Özgür. All right reserved. + + Contributors: + - Andre Koehler / info(at)tomate-online(dot)de + - Gordeev Andrey Vladimirovich / gordeev(at)openpyro(dot)com + - Skineffect / http://forum.ardumote.com/viewtopic.php?f=2&t=46 + - Dominik Fischer / dom_fischer(at)web(dot)de + - Frank Oltmanns / .(at)gmail(dot)com + - Max Horn / max(at)quendi(dot)de + - Robert ter Vehn / .(at)gmail(dot)com + + Project home: https://github.com/sui77/rc-switch/ + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ +#ifndef _RCSwitch_h +#define _RCSwitch_h + +#if defined(ARDUINO) && ARDUINO >= 100 + #include "Arduino.h" +#elif defined(ENERGIA) // LaunchPad, FraunchPad and StellarPad specific + #include "Energia.h" +#elif defined(RPI) // Raspberry Pi + #define RaspberryPi + + // Include libraries for RPi: + #include /* memcpy */ + #include /* abs */ + #include +#elif defined(SPARK) + #include "application.h" +#else + #include "WProgram.h" +#endif + +#include + + +// At least for the ATTiny X4/X5, receiving has to be disabled due to +// missing libm depencies (udivmodhi4) +#if defined( __AVR_ATtinyX5__ ) or defined ( __AVR_ATtinyX4__ ) +#define RCSwitchDisableReceiving +#endif + +// Number of maximum high/Low changes per packet. +// We can handle up to (unsigned long) => 32 bit * 2 H/L changes per bit + 2 for sync +#define RCSWITCH_MAX_CHANGES 67 + +class RCSwitch { + + public: + RCSwitch(); + + void switchOn(int nGroupNumber, int nSwitchNumber); + void switchOff(int nGroupNumber, int nSwitchNumber); + void switchOn(const char* sGroup, int nSwitchNumber); + void switchOff(const char* sGroup, int nSwitchNumber); + void switchOn(char sFamily, int nGroup, int nDevice); + void switchOff(char sFamily, int nGroup, int nDevice); + void switchOn(const char* sGroup, const char* sDevice); + void switchOff(const char* sGroup, const char* sDevice); + void switchOn(char sGroup, int nDevice); + void switchOff(char sGroup, int nDevice); + + void sendTriState(const char* sCodeWord); + void send(unsigned long code, unsigned int length); + void send(const char* sCodeWord); + + #if not defined( RCSwitchDisableReceiving ) + void enableReceive(int interrupt); + void enableReceive(); + void disableReceive(); + bool available(); + void resetAvailable(); + + unsigned long getReceivedValue(); + unsigned int getReceivedBitlength(); + unsigned int getReceivedDelay(); + unsigned int getReceivedProtocol(); + unsigned int* getReceivedRawdata(); + #endif + + void enableTransmit(int nTransmitterPin); + void disableTransmit(); + void setPulseLength(int nPulseLength); + void setRepeatTransmit(int nRepeatTransmit); + #if not defined( RCSwitchDisableReceiving ) + void setReceiveTolerance(int nPercent); + #endif + + /** + * Description of a single pule, which consists of a high signal + * whose duration is "high" times the base pulse length, followed + * by a low signal lasting "low" times the base pulse length. + * Thus, the pulse overall lasts (high+low)*pulseLength + */ + struct HighLow { + uint8_t high; + uint8_t low; + }; + + /** + * A "protocol" describes how zero and one bits are encoded into high/low + * pulses. + */ + struct Protocol { + /** base pulse length in microseconds, e.g. 350 */ + uint16_t pulseLength; + + HighLow syncFactor; + HighLow zero; + HighLow one; + + /** + * If true, interchange high and low logic levels in all transmissions. + * + * By default, RCSwitch assumes that any signals it sends or receives + * can be broken down into pulses which start with a high signal level, + * followed by a a low signal level. This is e.g. the case for the + * popular PT 2260 encoder chip, and thus many switches out there. + * + * But some devices do it the other way around, and start with a low + * signal level, followed by a high signal level, e.g. the HT6P20B. To + * accommodate this, one can set invertedSignal to true, which causes + * RCSwitch to change how it interprets any HighLow struct FOO: It will + * then assume transmissions start with a low signal lasting + * FOO.high*pulseLength microseconds, followed by a high signal lasting + * FOO.low*pulseLength microseconds. + */ + bool invertedSignal; + }; + + void setProtocol(Protocol protocol); + void setProtocol(int nProtocol); + void setProtocol(int nProtocol, int nPulseLength); + + private: + char* getCodeWordA(const char* sGroup, const char* sDevice, bool bStatus); + char* getCodeWordB(int nGroupNumber, int nSwitchNumber, bool bStatus); + char* getCodeWordC(char sFamily, int nGroup, int nDevice, bool bStatus); + char* getCodeWordD(char group, int nDevice, bool bStatus); + void transmit(HighLow pulses); + + #if not defined( RCSwitchDisableReceiving ) + static void handleInterrupt(); + static bool receiveProtocol(const int p, unsigned int changeCount); + int nReceiverInterrupt; + #endif + int nTransmitterPin; + int nRepeatTransmit; + + Protocol protocol; + + #if not defined( RCSwitchDisableReceiving ) + static int nReceiveTolerance; + volatile static unsigned long nReceivedValue; + volatile static unsigned int nReceivedBitlength; + volatile static unsigned int nReceivedDelay; + volatile static unsigned int nReceivedProtocol; + const static unsigned int nSeparationLimit; + /* + * timings[0] contains sync timing, followed by a number of bits + */ + static unsigned int timings[RCSWITCH_MAX_CHANGES]; + #endif + + +}; + +#endif diff --git a/Software/ATmega32U4_nl/RF24.cpp b/Software/ATmega32U4_nl/RF24.cpp new file mode 100644 index 0000000..d71402c --- /dev/null +++ b/Software/ATmega32U4_nl/RF24.cpp @@ -0,0 +1,1678 @@ +/* + Copyright (C) 2011 J. Coliz + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + */ + +#include "nRF24L01.h" +#include "RF24_config.h" +#include "RF24.h" + +/****************************************************************************/ + +void RF24::csn(bool mode) +{ + +#if defined (RF24_TINY) + if (ce_pin != csn_pin) { + digitalWrite(csn_pin,mode); + } + else { + if (mode == HIGH) { + PORTB |= (1<CSN HIGH + delayMicroseconds(100); // allow csn to settle. + } + else { + PORTB &= ~(1<CSN LOW + delayMicroseconds(11); // allow csn to settle + } + } + // Return, CSN toggle complete + return; + +#elif defined(ARDUINO) && !defined (RF24_SPI_TRANSACTIONS) + // Minimum ideal SPI bus speed is 2x data rate + // If we assume 2Mbs data rate and 16Mhz clock, a + // divider of 4 is the minimum we want. + // CLK:BUS 8Mhz:2Mhz, 16Mhz:4Mhz, or 20Mhz:5Mhz + + #if !defined (SOFTSPI) + _SPI.setBitOrder(MSBFIRST); + _SPI.setDataMode(SPI_MODE0); + _SPI.setClockDivider(SPI_CLOCK_DIV2); + #endif +#elif defined (RF24_RPi) + if(!mode) + _SPI.chipSelect(csn_pin); +#endif + +#if !defined (RF24_LINUX) + digitalWrite(csn_pin,mode); + delayMicroseconds(csDelay); +#endif + +} + +/****************************************************************************/ + +void RF24::ce(bool level) +{ + //Allow for 3-pin use on ATTiny + if (ce_pin != csn_pin) digitalWrite(ce_pin,level); +} + +/****************************************************************************/ + + inline void RF24::beginTransaction() { + #if defined (RF24_SPI_TRANSACTIONS) + _SPI.beginTransaction(SPISettings(RF24_SPI_SPEED, MSBFIRST, SPI_MODE0)); + #endif + csn(LOW); + } + +/****************************************************************************/ + + inline void RF24::endTransaction() { + csn(HIGH); + #if defined (RF24_SPI_TRANSACTIONS) + _SPI.endTransaction(); + #endif + } + +/****************************************************************************/ + +uint8_t RF24::read_register(uint8_t reg, uint8_t* buf, uint8_t len) +{ + uint8_t status; + + #if defined (RF24_LINUX) + beginTransaction(); //configures the spi settings for RPi, locks mutex and setting csn low + uint8_t * prx = spi_rxbuff; + uint8_t * ptx = spi_txbuff; + uint8_t size = len + 1; // Add register value to transmit buffer + + *ptx++ = ( R_REGISTER | ( REGISTER_MASK & reg ) ); + + while (len--){ *ptx++ = RF24_NOP; } // Dummy operation, just for reading + + _SPI.transfernb( (char *) spi_txbuff, (char *) spi_rxbuff, size); + + status = *prx++; // status is 1st byte of receive buffer + + // decrement before to skip status byte + while ( --size ){ *buf++ = *prx++; } + endTransaction(); //unlocks mutex and setting csn high + +#else + + beginTransaction(); + status = _SPI.transfer( R_REGISTER | ( REGISTER_MASK & reg ) ); + while ( len-- ){ + *buf++ = _SPI.transfer(0xff); + } + endTransaction(); + +#endif + + return status; +} + +/****************************************************************************/ + +uint8_t RF24::read_register(uint8_t reg) +{ + uint8_t result; + + #if defined (RF24_LINUX) + + beginTransaction(); + + uint8_t * prx = spi_rxbuff; + uint8_t * ptx = spi_txbuff; + *ptx++ = ( R_REGISTER | ( REGISTER_MASK & reg ) ); + *ptx++ = RF24_NOP ; // Dummy operation, just for reading + + _SPI.transfernb( (char *) spi_txbuff, (char *) spi_rxbuff, 2); + result = *++prx; // result is 2nd byte of receive buffer + + endTransaction(); + #else + + beginTransaction(); + _SPI.transfer( R_REGISTER | ( REGISTER_MASK & reg ) ); + result = _SPI.transfer(0xff); + endTransaction(); + + #endif + + return result; +} + +/****************************************************************************/ + +uint8_t RF24::write_register(uint8_t reg, const uint8_t* buf, uint8_t len) +{ + uint8_t status; + + #if defined (RF24_LINUX) + beginTransaction(); + uint8_t * prx = spi_rxbuff; + uint8_t * ptx = spi_txbuff; + uint8_t size = len + 1; // Add register value to transmit buffer + + *ptx++ = ( W_REGISTER | ( REGISTER_MASK & reg ) ); + while ( len-- ) + *ptx++ = *buf++; + + _SPI.transfernb( (char *) spi_txbuff, (char *) spi_rxbuff, size); + status = *prx; // status is 1st byte of receive buffer + endTransaction(); + #else + + beginTransaction(); + status = _SPI.transfer( W_REGISTER | ( REGISTER_MASK & reg ) ); + while ( len-- ) + _SPI.transfer(*buf++); + endTransaction(); + + #endif + + return status; +} + +/****************************************************************************/ + +uint8_t RF24::write_register(uint8_t reg, uint8_t value) +{ + uint8_t status; + + IF_SERIAL_DEBUG(printf_P(PSTR("write_register(%02x,%02x)\r\n"),reg,value)); + + #if defined (RF24_LINUX) + beginTransaction(); + uint8_t * prx = spi_rxbuff; + uint8_t * ptx = spi_txbuff; + *ptx++ = ( W_REGISTER | ( REGISTER_MASK & reg ) ); + *ptx = value ; + + _SPI.transfernb( (char *) spi_txbuff, (char *) spi_rxbuff, 2); + status = *prx++; // status is 1st byte of receive buffer + endTransaction(); + #else + + beginTransaction(); + status = _SPI.transfer( W_REGISTER | ( REGISTER_MASK & reg ) ); + _SPI.transfer(value); + endTransaction(); + + #endif + + return status; +} + +/****************************************************************************/ + +uint8_t RF24::write_payload(const void* buf, uint8_t data_len, const uint8_t writeType) +{ + uint8_t status; + const uint8_t* current = reinterpret_cast(buf); + + data_len = rf24_min(data_len, payload_size); + uint8_t blank_len = dynamic_payloads_enabled ? 0 : payload_size - data_len; + + //printf("[Writing %u bytes %u blanks]",data_len,blank_len); + IF_SERIAL_DEBUG( printf("[Writing %u bytes %u blanks]\n",data_len,blank_len); ); + + #if defined (RF24_LINUX) + beginTransaction(); + uint8_t * prx = spi_rxbuff; + uint8_t * ptx = spi_txbuff; + uint8_t size; + size = data_len + blank_len + 1 ; // Add register value to transmit buffer + + *ptx++ = writeType; + while ( data_len-- ) + *ptx++ = *current++; + while ( blank_len-- ) + *ptx++ = 0; + + _SPI.transfernb( (char *) spi_txbuff, (char *) spi_rxbuff, size); + status = *prx; // status is 1st byte of receive buffer + endTransaction(); + + #else + + beginTransaction(); + status = _SPI.transfer( writeType ); + while ( data_len-- ) { + _SPI.transfer(*current++); + } + while ( blank_len-- ) { + _SPI.transfer(0); + } + endTransaction(); + + #endif + + return status; +} + +/****************************************************************************/ + +uint8_t RF24::read_payload(void* buf, uint8_t data_len) +{ + uint8_t status; + uint8_t* current = reinterpret_cast(buf); + + if(data_len > payload_size) data_len = payload_size; + uint8_t blank_len = dynamic_payloads_enabled ? 0 : payload_size - data_len; + + //printf("[Reading %u bytes %u blanks]",data_len,blank_len); + + IF_SERIAL_DEBUG( printf("[Reading %u bytes %u blanks]\n",data_len,blank_len); ); + + #if defined (RF24_LINUX) + beginTransaction(); + uint8_t * prx = spi_rxbuff; + uint8_t * ptx = spi_txbuff; + uint8_t size; + size = data_len + blank_len + 1; // Add register value to transmit buffer + + *ptx++ = R_RX_PAYLOAD; + while(--size) + *ptx++ = RF24_NOP; + + size = data_len + blank_len + 1; // Size has been lost during while, re affect + + _SPI.transfernb( (char *) spi_txbuff, (char *) spi_rxbuff, size); + + status = *prx++; // 1st byte is status + + if (data_len > 0) { + while ( --data_len ) // Decrement before to skip 1st status byte + *current++ = *prx++; + + *current = *prx; + } + endTransaction(); + #else + + beginTransaction(); + status = _SPI.transfer( R_RX_PAYLOAD ); + while ( data_len-- ) { + *current++ = _SPI.transfer(0xFF); + } + while ( blank_len-- ) { + _SPI.transfer(0xff); + } + endTransaction(); + + #endif + + return status; +} + +/****************************************************************************/ +uint8_t RF24::Reader(void* buf){ + uint8_t rx_len = read_register(R_RX_PAYLOAD); + +/* if(rx_len>0 && rx_len<33) + { + NRF_CE_L(); + readBuf(CMD_R_RX_PAYLOAD,rx_buf,rx_len); + NRF_CE_H(); + read_payload( buf, len ); + }*/ + +// NRF_CE_L(); +// read_register(R_RX_PAYLOAD,buf,5); +// NRF_CE_H(); + read_payload( buf, 5 ); + write_register(NRF_STATUS,_BV(RX_DR) | _BV(MAX_RT) | _BV(TX_DS) ); + return rx_len; + +} + + +/****************************************************************************/ + +uint8_t RF24::flush_rx(void) +{ + return spiTrans( FLUSH_RX ); +} + +/****************************************************************************/ + +uint8_t RF24::flush_tx(void) +{ + return spiTrans( FLUSH_TX ); +} + +/****************************************************************************/ + +uint8_t RF24::spiTrans(uint8_t cmd){ + + uint8_t status; + + beginTransaction(); + status = _SPI.transfer( cmd ); + endTransaction(); + + return status; +} + +/****************************************************************************/ + +uint8_t RF24::get_status(void) +{ + return spiTrans(RF24_NOP); +} + +/****************************************************************************/ +#if !defined (MINIMAL) +void RF24::print_status(uint8_t status) +{ + printf_P(PSTR("STATUS\t\t = 0x%02x RX_DR=%x TX_DS=%x MAX_RT=%x RX_P_NO=%x TX_FULL=%x\r\n"), + status, + (status & _BV(RX_DR))?1:0, + (status & _BV(TX_DS))?1:0, + (status & _BV(MAX_RT))?1:0, + ((status >> RX_P_NO) & 0x07), + (status & _BV(TX_FULL))?1:0 + ); +} + +/****************************************************************************/ + +void RF24::print_observe_tx(uint8_t value) +{ + printf_P(PSTR("OBSERVE_TX=%02x: POLS_CNT=%x ARC_CNT=%x\r\n"), + value, + (value >> PLOS_CNT) & 0x0F, + (value >> ARC_CNT) & 0x0F + ); +} + +/****************************************************************************/ + +void RF24::print_byte_register(const char* name, uint8_t reg, uint8_t qty) +{ + //char extra_tab = strlen_P(name) < 8 ? '\t' : 0; + //printf_P(PSTR(PRIPSTR"\t%c ="),name,extra_tab); + #if defined (RF24_LINUX) + printf("%s\t =", name); + #else + printf_P(PSTR(PRIPSTR"\t ="),name); + #endif + while (qty--) + printf_P(PSTR(" 0x%02x"),read_register(reg++)); + printf_P(PSTR("\r\n")); +} + +/****************************************************************************/ + +void RF24::print_address_register(const char* name, uint8_t reg, uint8_t qty) +{ + + #if defined (RF24_LINUX) + printf("%s\t =",name); + #else + printf_P(PSTR(PRIPSTR"\t ="),name); + #endif + while (qty--) + { + uint8_t buffer[addr_width]; + read_register(reg++,buffer,sizeof buffer); + + printf_P(PSTR(" 0x")); + uint8_t* bufptr = buffer + sizeof buffer; + while( --bufptr >= buffer ) + printf_P(PSTR("%02x"),*bufptr); + } + + printf_P(PSTR("\r\n")); +} +#endif +/****************************************************************************/ + +RF24::RF24(uint16_t _cepin, uint16_t _cspin): + ce_pin(_cepin), csn_pin(_cspin), p_variant(false), + payload_size(32), dynamic_payloads_enabled(false), addr_width(5),csDelay(5)//,pipe0_reading_address(0) +{ + pipe0_reading_address[0]=0; +} + +/****************************************************************************/ + +#if defined (RF24_LINUX) && !defined (MRAA)//RPi constructor + +RF24::RF24(uint16_t _cepin, uint16_t _cspin, uint32_t _spi_speed): + ce_pin(_cepin),csn_pin(_cspin),spi_speed(_spi_speed),p_variant(false), payload_size(32), dynamic_payloads_enabled(false),addr_width(5)//,pipe0_reading_address(0) +{ + pipe0_reading_address[0]=0; +} +#endif + +/****************************************************************************/ + +void RF24::setChannel(uint8_t channel) +{ + const uint8_t max_channel = 125; + write_register(RF_CH,rf24_min(channel,max_channel)); +} + +uint8_t RF24::getChannel() +{ + + return read_register(RF_CH); +} +/****************************************************************************/ + +void RF24::setPayloadSize(uint8_t size) +{ + payload_size = rf24_min(size,32); +} + +/****************************************************************************/ + +uint8_t RF24::getPayloadSize(void) +{ + return payload_size; +} + +/****************************************************************************/ + +#if !defined (MINIMAL) + +static const char rf24_datarate_e_str_0[] PROGMEM = "1MBPS"; +static const char rf24_datarate_e_str_1[] PROGMEM = "2MBPS"; +static const char rf24_datarate_e_str_2[] PROGMEM = "250KBPS"; +static const char * const rf24_datarate_e_str_P[] PROGMEM = { + rf24_datarate_e_str_0, + rf24_datarate_e_str_1, + rf24_datarate_e_str_2, +}; +static const char rf24_model_e_str_0[] PROGMEM = "nRF24L01"; +static const char rf24_model_e_str_1[] PROGMEM = "nRF24L01+"; +static const char * const rf24_model_e_str_P[] PROGMEM = { + rf24_model_e_str_0, + rf24_model_e_str_1, +}; +static const char rf24_crclength_e_str_0[] PROGMEM = "Disabled"; +static const char rf24_crclength_e_str_1[] PROGMEM = "8 bits"; +static const char rf24_crclength_e_str_2[] PROGMEM = "16 bits" ; +static const char * const rf24_crclength_e_str_P[] PROGMEM = { + rf24_crclength_e_str_0, + rf24_crclength_e_str_1, + rf24_crclength_e_str_2, +}; +static const char rf24_pa_dbm_e_str_0[] PROGMEM = "PA_MIN"; +static const char rf24_pa_dbm_e_str_1[] PROGMEM = "PA_LOW"; +static const char rf24_pa_dbm_e_str_2[] PROGMEM = "PA_HIGH"; +static const char rf24_pa_dbm_e_str_3[] PROGMEM = "PA_MAX"; +static const char * const rf24_pa_dbm_e_str_P[] PROGMEM = { + rf24_pa_dbm_e_str_0, + rf24_pa_dbm_e_str_1, + rf24_pa_dbm_e_str_2, + rf24_pa_dbm_e_str_3, +}; + +#if defined (RF24_LINUX) +static const char rf24_csn_e_str_0[] = "CE0 (PI Hardware Driven)"; +static const char rf24_csn_e_str_1[] = "CE1 (PI Hardware Driven)"; +static const char rf24_csn_e_str_2[] = "CE2 (PI Hardware Driven)"; +static const char rf24_csn_e_str_3[] = "Custom GPIO Software Driven"; +static const char * const rf24_csn_e_str_P[] = { + rf24_csn_e_str_0, + rf24_csn_e_str_1, + rf24_csn_e_str_2, + rf24_csn_e_str_3, +}; +#endif + +void RF24::printDetails(void) +{ + +#if defined (RF24_RPi) + printf("================ SPI Configuration ================\n" ); + if (csn_pin < BCM2835_SPI_CS_NONE ){ + printf("CSN Pin \t = %s\n",rf24_csn_e_str_P[csn_pin]); + }else{ + printf("CSN Pin \t = Custom GPIO%d%s\n", csn_pin, + csn_pin==RPI_V2_GPIO_P1_26 ? " (CE1) Software Driven" : "" ); + } + printf("CE Pin \t = Custom GPIO%d\n", ce_pin ); + printf("Clock Speed\t = " ); + switch (spi_speed) + { + case BCM2835_SPI_SPEED_64MHZ : printf("64 Mhz"); break ; + case BCM2835_SPI_SPEED_32MHZ : printf("32 Mhz"); break ; + case BCM2835_SPI_SPEED_16MHZ : printf("16 Mhz"); break ; + case BCM2835_SPI_SPEED_8MHZ : printf("8 Mhz"); break ; + case BCM2835_SPI_SPEED_4MHZ : printf("4 Mhz"); break ; + case BCM2835_SPI_SPEED_2MHZ : printf("2 Mhz"); break ; + case BCM2835_SPI_SPEED_1MHZ : printf("1 Mhz"); break ; + case BCM2835_SPI_SPEED_512KHZ: printf("512 KHz"); break ; + case BCM2835_SPI_SPEED_256KHZ: printf("256 KHz"); break ; + case BCM2835_SPI_SPEED_128KHZ: printf("128 KHz"); break ; + case BCM2835_SPI_SPEED_64KHZ : printf("64 KHz"); break ; + case BCM2835_SPI_SPEED_32KHZ : printf("32 KHz"); break ; + case BCM2835_SPI_SPEED_16KHZ : printf("16 KHz"); break ; + case BCM2835_SPI_SPEED_8KHZ : printf("8 KHz"); break ; + default : printf("8 Mhz"); break ; + } + printf("\n================ NRF Configuration ================\n"); + +#endif //Linux + + print_status(get_status()); + + print_address_register(PSTR("RX_ADDR_P0-1"),RX_ADDR_P0,2); + print_address_register(PSTR("TX_ADDR\t"),TX_ADDR); + + print_byte_register(PSTR("RX_PW_P0-6"),RX_PW_P0,6); + print_byte_register(PSTR("EN_AA\t"),EN_AA); + print_byte_register(PSTR("EN_RXADDR"),EN_RXADDR); + print_byte_register(PSTR("RF_CH\t"),RF_CH); + print_byte_register(PSTR("RF_SETUP"),RF_SETUP); + print_byte_register(PSTR("CONFIG\t"),NRF_CONFIG); + print_byte_register(PSTR("DYNPD/FEATURE"),DYNPD,2); + + printf_P(PSTR("Data Rate\t = " PRIPSTR "\r\n"),pgm_read_word(&rf24_datarate_e_str_P[getDataRate()])); + printf_P(PSTR("Model\t\t = " PRIPSTR "\r\n"),pgm_read_word(&rf24_model_e_str_P[isPVariant()])); + printf_P(PSTR("CRC Length\t = " PRIPSTR "\r\n"),pgm_read_word(&rf24_crclength_e_str_P[getCRCLength()])); + printf_P(PSTR("PA Power\t = " PRIPSTR "\r\n"), pgm_read_word(&rf24_pa_dbm_e_str_P[getPALevel()])); + +} + +void RF24::print_config(void){ + for (int i=0;i<30;i++){ + Serial.print(i,HEX); + Serial.print(" "); + Serial.print(read_register(i),HEX); + Serial.println(" "); + } +} + + +#endif +/****************************************************************************/ + +bool RF24::begin(void) +{ + + uint8_t setup=0; + + #if defined (RF24_LINUX) + + #if defined (MRAA) + GPIO(); + gpio.begin(ce_pin,csn_pin); + #endif + + #ifdef RF24_RPi + switch(csn_pin){ //Ensure valid hardware CS pin + case 0: break; + case 1: break; + // Allow BCM2835 enums for RPi + case 8: csn_pin = 0; break; + case 7: csn_pin = 1; break; + default: csn_pin = 0; break; + } + #endif + + _SPI.begin(csn_pin); + + pinMode(ce_pin,OUTPUT); + ce(LOW); + + delay(100); + + #elif defined(LITTLEWIRE) + pinMode(csn_pin,OUTPUT); + _SPI.begin(); + csn(HIGH); + #elif defined(XMEGA_D3) + if (ce_pin != csn_pin) pinMode(ce_pin,OUTPUT); + _SPI.begin(csn_pin); + ce(LOW); + csn(HIGH); + delay(200); + #else + // Initialize pins + if (ce_pin != csn_pin) pinMode(ce_pin,OUTPUT); + + #if ! defined(LITTLEWIRE) + if (ce_pin != csn_pin) + #endif + pinMode(csn_pin,OUTPUT); + + _SPI.begin(); + ce(LOW); + csn(HIGH); + #if defined (__ARDUINO_X86__) + delay(100); + #endif + #endif //Linux + + // Must allow the radio time to settle else configuration bits will not necessarily stick. + // This is actually only required following power up but some settling time also appears to + // be required after resets too. For full coverage, we'll always assume the worst. + // Enabling 16b CRC is by far the most obvious case if the wrong timing is used - or skipped. + // Technically we require 4.5ms + 14us as a worst case. We'll just call it 5ms for good measure. + // WARNING: Delay is based on P-variant whereby non-P *may* require different timing. + delay( 5 ) ; + + // Reset NRF_CONFIG and enable 16-bit CRC. + write_register( NRF_CONFIG, 0x0C ) ; + + // Set 1500uS (minimum for 32B payload in ESB@250KBPS) timeouts, to make testing a little easier + // WARNING: If this is ever lowered, either 250KBS mode with AA is broken or maximum packet + // sizes must never be used. See documentation for a more complete explanation. + setRetries(5,15); + + // Reset value is MAX + //setPALevel( RF24_PA_MAX ) ; + + // check for connected module and if this is a p nRF24l01 variant + // + if( setDataRate( RF24_250KBPS ) ) + { + p_variant = true ; + } + setup = read_register(RF_SETUP); + /*if( setup == 0b00001110 ) // register default for nRF24L01P + { + p_variant = true ; + }*/ + + // Then set the data rate to the slowest (and most reliable) speed supported by all + // hardware. + setDataRate( RF24_1MBPS ) ; + + // Initialize CRC and request 2-byte (16bit) CRC + //setCRCLength( RF24_CRC_16 ) ; + + // Disable dynamic payloads, to match dynamic_payloads_enabled setting - Reset value is 0 + toggle_features(); + write_register(FEATURE,0 ); + write_register(DYNPD,0); + dynamic_payloads_enabled = false; + + // Reset current status + // Notice reset and flush is the last thing we do + write_register(NRF_STATUS,_BV(RX_DR) | _BV(TX_DS) | _BV(MAX_RT) ); + + // Set up default configuration. Callers can always change it later. + // This channel should be universally safe and not bleed over into adjacent + // spectrum. + setChannel(76); + + // Flush buffers + flush_rx(); + flush_tx(); + + powerUp(); //Power up by default when begin() is called + + // Enable PTX, do not write CE high so radio will remain in standby I mode ( 130us max to transition to RX or TX instead of 1500us from powerUp ) + // PTX should use only 22uA of power + write_register(NRF_CONFIG, ( read_register(NRF_CONFIG) ) & ~_BV(PRIM_RX) ); + + // if setup is 0 or ff then there was no response from module + return ( setup != 0 && setup != 0xff ); +} + +/****************************************************************************/ + +bool RF24::isChipConnected() +{ + uint8_t setup = read_register(SETUP_AW); + if(setup >= 1 && setup <= 3) + { + return true; + } + + return false; +} + +/****************************************************************************/ + +void RF24::startListening(void) +{ + #if !defined (RF24_TINY) && ! defined(LITTLEWIRE) + powerUp(); + #endif + write_register(NRF_CONFIG, read_register(NRF_CONFIG) | _BV(PRIM_RX)); + write_register(NRF_STATUS, _BV(RX_DR) | _BV(TX_DS) | _BV(MAX_RT) ); + ce(HIGH); + // Restore the pipe0 adddress, if exists + if (pipe0_reading_address[0] > 0){ + write_register(RX_ADDR_P0, pipe0_reading_address, addr_width); + }else{ + closeReadingPipe(0); + } + + // Flush buffers + //flush_rx(); + if(read_register(FEATURE) & _BV(EN_ACK_PAY)){ + flush_tx(); + } + + // Go! + //delayMicroseconds(100); +} + +/****************************************************************************/ +static const uint8_t child_pipe_enable[] PROGMEM = +{ + ERX_P0, ERX_P1, ERX_P2, ERX_P3, ERX_P4, ERX_P5 +}; + +void RF24::stopListening(void) +{ + ce(LOW); + + delayMicroseconds(txDelay); + + if(read_register(FEATURE) & _BV(EN_ACK_PAY)){ + delayMicroseconds(txDelay); //200 + flush_tx(); + } + //flush_rx(); + write_register(NRF_CONFIG, ( read_register(NRF_CONFIG) ) & ~_BV(PRIM_RX) ); + + #if defined (RF24_TINY) || defined (LITTLEWIRE) + // for 3 pins solution TX mode is only left with additonal powerDown/powerUp cycle + if (ce_pin == csn_pin) { + powerDown(); + powerUp(); + } + #endif + write_register(EN_RXADDR,read_register(EN_RXADDR) | _BV(pgm_read_byte(&child_pipe_enable[0]))); // Enable RX on pipe0 + + //delayMicroseconds(100); + +} + +/****************************************************************************/ + +void RF24::powerDown(void) +{ + ce(LOW); // Guarantee CE is low on powerDown + write_register(NRF_CONFIG,read_register(NRF_CONFIG) & ~_BV(PWR_UP)); +} + +/****************************************************************************/ + +//Power up now. Radio will not power down unless instructed by MCU for config changes etc. +void RF24::powerUp(void) +{ + uint8_t cfg = read_register(NRF_CONFIG); + + // if not powered up then power up and wait for the radio to initialize + if (!(cfg & _BV(PWR_UP))){ + write_register(NRF_CONFIG, cfg | _BV(PWR_UP)); + + // For nRF24L01+ to go from power down mode to TX or RX mode it must first pass through stand-by mode. + // There must be a delay of Tpd2stby (see Table 16.) after the nRF24L01+ leaves power down mode before + // the CEis set high. - Tpd2stby can be up to 5ms per the 1.0 datasheet + delay(5); + } +} + +/******************************************************************/ +#if defined (FAILURE_HANDLING) || defined (RF24_LINUX) +void RF24::errNotify(){ + #if defined (SERIAL_DEBUG) || defined (RF24_LINUX) + printf_P(PSTR("RF24 HARDWARE FAIL: Radio not responding, verify pin connections, wiring, etc.\r\n")); + #endif + #if defined (FAILURE_HANDLING) + failureDetected = 1; + #else + delay(5000); + #endif +} +#endif +/******************************************************************/ + +//Similar to the previous write, clears the interrupt flags +bool RF24::write( const void* buf, uint8_t len, const bool multicast ) +{ + //Start Writing + startFastWrite(buf,len,multicast); + + //Wait until complete or failed + #if defined (FAILURE_HANDLING) || defined (RF24_LINUX) + uint32_t timer = millis(); + #endif + + while( ! ( get_status() & ( _BV(TX_DS) | _BV(MAX_RT) ))) { + #if defined (FAILURE_HANDLING) || defined (RF24_LINUX) + if(millis() - timer > 95){ + errNotify(); + #if defined (FAILURE_HANDLING) + return 0; + #else + delay(100); + #endif + } + #endif + } + + ce(LOW); + + uint8_t status = write_register(NRF_STATUS,_BV(RX_DR) | _BV(TX_DS) | _BV(MAX_RT) ); + + //Max retries exceeded + if( status & _BV(MAX_RT)){ + flush_tx(); //Only going to be 1 packet int the FIFO at a time using this method, so just flush + return 0; + } + //TX OK 1 or 0 + return 1; +} + +bool RF24::write( const void* buf, uint8_t len ){ + return write(buf,len,0); +} +/****************************************************************************/ + +//For general use, the interrupt flags are not important to clear +bool RF24::writeBlocking( const void* buf, uint8_t len, uint32_t timeout ) +{ + //Block until the FIFO is NOT full. + //Keep track of the MAX retries and set auto-retry if seeing failures + //This way the FIFO will fill up and allow blocking until packets go through + //The radio will auto-clear everything in the FIFO as long as CE remains high + + uint32_t timer = millis(); //Get the time that the payload transmission started + + while( ( get_status() & ( _BV(TX_FULL) ))) { //Blocking only if FIFO is full. This will loop and block until TX is successful or timeout + + if( get_status() & _BV(MAX_RT)){ //If MAX Retries have been reached + reUseTX(); //Set re-transmit and clear the MAX_RT interrupt flag + if(millis() - timer > timeout){ return 0; } //If this payload has exceeded the user-defined timeout, exit and return 0 + } + #if defined (FAILURE_HANDLING) || defined (RF24_LINUX) + if(millis() - timer > (timeout+95) ){ + errNotify(); + #if defined (FAILURE_HANDLING) + return 0; + #endif + } + #endif + + } + + //Start Writing + startFastWrite(buf,len,0); //Write the payload if a buffer is clear + + return 1; //Return 1 to indicate successful transmission +} + +/****************************************************************************/ + +void RF24::reUseTX(){ + write_register(NRF_STATUS,_BV(MAX_RT) ); //Clear max retry flag + spiTrans( REUSE_TX_PL ); + ce(LOW); //Re-Transfer packet + ce(HIGH); +} + +/****************************************************************************/ + +bool RF24::writeFast( const void* buf, uint8_t len, const bool multicast ) +{ + //Block until the FIFO is NOT full. + //Keep track of the MAX retries and set auto-retry if seeing failures + //Return 0 so the user can control the retrys and set a timer or failure counter if required + //The radio will auto-clear everything in the FIFO as long as CE remains high + + #if defined (FAILURE_HANDLING) || defined (RF24_LINUX) + uint32_t timer = millis(); + #endif + + while( ( get_status() & ( _BV(TX_FULL) ))) { //Blocking only if FIFO is full. This will loop and block until TX is successful or fail + + if( get_status() & _BV(MAX_RT)){ + //reUseTX(); //Set re-transmit + write_register(NRF_STATUS,_BV(MAX_RT) ); //Clear max retry flag + return 0; //Return 0. The previous payload has been retransmitted + //From the user perspective, if you get a 0, just keep trying to send the same payload + } + #if defined (FAILURE_HANDLING) || defined (RF24_LINUX) + if(millis() - timer > 95 ){ + errNotify(); + #if defined (FAILURE_HANDLING) + return 0; + #endif + } + #endif + } + //Start Writing + startFastWrite(buf,len,multicast); + + return 1; +} + +bool RF24::writeFast( const void* buf, uint8_t len ){ + return writeFast(buf,len,0); +} + +/****************************************************************************/ + +//Per the documentation, we want to set PTX Mode when not listening. Then all we do is write data and set CE high +//In this mode, if we can keep the FIFO buffers loaded, packets will transmit immediately (no 130us delay) +//Otherwise we enter Standby-II mode, which is still faster than standby mode +//Also, we remove the need to keep writing the config register over and over and delaying for 150 us each time if sending a stream of data + +void RF24::startFastWrite( const void* buf, uint8_t len, const bool multicast, bool startTx){ //TMRh20 + + //write_payload( buf,len); + write_payload( buf, len,multicast ? W_TX_PAYLOAD_NO_ACK : W_TX_PAYLOAD ) ; + if(startTx){ + ce(HIGH); + } + +} + +/****************************************************************************/ + +//Added the original startWrite back in so users can still use interrupts, ack payloads, etc +//Allows the library to pass all tests +void RF24::startWrite( const void* buf, uint8_t len, const bool multicast ){ + + // Send the payload + + //write_payload( buf, len ); + write_payload( buf, len,multicast? W_TX_PAYLOAD_NO_ACK : W_TX_PAYLOAD ) ; + ce(HIGH); + #if defined(CORE_TEENSY) || !defined(ARDUINO) || defined (RF24_SPIDEV) || defined (RF24_DUE) + delayMicroseconds(10); + #endif + ce(LOW); + + +} + +/****************************************************************************/ + +bool RF24::rxFifoFull(){ + return read_register(FIFO_STATUS) & _BV(RX_FULL); +} +/****************************************************************************/ + +bool RF24::txStandBy(){ + + #if defined (FAILURE_HANDLING) || defined (RF24_LINUX) + uint32_t timeout = millis(); + #endif + while( ! (read_register(FIFO_STATUS) & _BV(TX_EMPTY)) ){ + if( get_status() & _BV(MAX_RT)){ + write_register(NRF_STATUS,_BV(MAX_RT) ); + ce(LOW); + flush_tx(); //Non blocking, flush the data + return 0; + } + #if defined (FAILURE_HANDLING) || defined (RF24_LINUX) + if( millis() - timeout > 95){ + errNotify(); + #if defined (FAILURE_HANDLING) + return 0; + #endif + } + #endif + } + + ce(LOW); //Set STANDBY-I mode + return 1; +} + +/****************************************************************************/ + +bool RF24::txStandBy(uint32_t timeout, bool startTx){ + + if(startTx){ + stopListening(); + ce(HIGH); + } + uint32_t start = millis(); + + while( ! (read_register(FIFO_STATUS) & _BV(TX_EMPTY)) ){ + if( get_status() & _BV(MAX_RT)){ + write_register(NRF_STATUS,_BV(MAX_RT) ); + ce(LOW); //Set re-transmit + ce(HIGH); + if(millis() - start >= timeout){ + ce(LOW); flush_tx(); return 0; + } + } + #if defined (FAILURE_HANDLING) || defined (RF24_LINUX) + if( millis() - start > (timeout+95)){ + errNotify(); + #if defined (FAILURE_HANDLING) + return 0; + #endif + } + #endif + } + + + ce(LOW); //Set STANDBY-I mode + return 1; + +} + +/****************************************************************************/ + +void RF24::maskIRQ(bool tx, bool fail, bool rx){ + + uint8_t config = read_register(NRF_CONFIG); + /* clear the interrupt flags */ + config &= ~(1 << MASK_MAX_RT | 1 << MASK_TX_DS | 1 << MASK_RX_DR); + /* set the specified interrupt flags */ + config |= fail << MASK_MAX_RT | tx << MASK_TX_DS | rx << MASK_RX_DR; + write_register(NRF_CONFIG, config); +} + +/****************************************************************************/ + +uint8_t RF24::getDynamicPayloadSize(void) +{ + uint8_t result = 0; + + #if defined (RF24_LINUX) + spi_txbuff[0] = R_RX_PL_WID; + spi_rxbuff[1] = 0xff; + beginTransaction(); + _SPI.transfernb( (char *) spi_txbuff, (char *) spi_rxbuff, 2); + result = spi_rxbuff[1]; + endTransaction(); + #else + beginTransaction(); + _SPI.transfer( R_RX_PL_WID ); + result = _SPI.transfer(0xff); + endTransaction(); + #endif + + if(result > 32) { flush_rx(); delay(2); return 0; } + return result; +} + +/****************************************************************************/ + +bool RF24::available(void) +{ + return available(NULL); +} + +/****************************************************************************/ + +bool RF24::available(uint8_t* pipe_num) +{ + if (!( read_register(FIFO_STATUS) & _BV(RX_EMPTY) )){ + + // If the caller wants the pipe number, include that + if ( pipe_num ){ + uint8_t status = get_status(); + *pipe_num = ( status >> RX_P_NO ) & 0x07; + } + return 1; + } + + + return 0; + + +} + +/****************************************************************************/ + +void RF24::read( void* buf, uint8_t len ){ + + // Fetch the payload + read_payload( buf, len ); + + //Clear the two possible interrupt flags with one command + write_register(NRF_STATUS,_BV(RX_DR) | _BV(MAX_RT) | _BV(TX_DS) ); + +} + +/****************************************************************************/ + +void RF24::whatHappened(bool& tx_ok,bool& tx_fail,bool& rx_ready) +{ + // Read the status & reset the status in one easy call + // Or is that such a good idea? + uint8_t status = write_register(NRF_STATUS,_BV(RX_DR) | _BV(TX_DS) | _BV(MAX_RT) ); + + // Report to the user what happened + tx_ok = status & _BV(TX_DS); + tx_fail = status & _BV(MAX_RT); + rx_ready = status & _BV(RX_DR); +} + +/****************************************************************************/ + +void RF24::openWritingPipe(uint64_t value) +{ + // Note that AVR 8-bit uC's store this LSB first, and the NRF24L01(+) + // expects it LSB first too, so we're good. + + write_register(RX_ADDR_P0, reinterpret_cast(&value), addr_width); + write_register(TX_ADDR, reinterpret_cast(&value), addr_width); + + + //const uint8_t max_payload_size = 32; + //write_register(RX_PW_P0,rf24_min(payload_size,max_payload_size)); + write_register(RX_PW_P0,payload_size); +} + +/****************************************************************************/ +void RF24::openWritingPipe(const uint8_t *address) +{ + // Note that AVR 8-bit uC's store this LSB first, and the NRF24L01(+) + // expects it LSB first too, so we're good. + + write_register(RX_ADDR_P0,address, addr_width); + write_register(TX_ADDR, address, addr_width); + + //const uint8_t max_payload_size = 32; + //write_register(RX_PW_P0,rf24_min(payload_size,max_payload_size)); + write_register(RX_PW_P0,payload_size); +} + + +void RF24::openWritingPipe(const uint8_t *address,int len ) +{ + // Note that AVR 8-bit uC's store this LSB first, and the NRF24L01(+) + // expects it LSB first too, so we're good. + + write_register(RX_ADDR_P0,address, len); + write_register(TX_ADDR, address, len); + + //const uint8_t max_payload_size = 32; + //write_register(RX_PW_P0,rf24_min(payload_size,max_payload_size)); + write_register(RX_PW_P0,payload_size); +} +/****************************************************************************/ +static const uint8_t child_pipe[] PROGMEM = +{ + RX_ADDR_P0, RX_ADDR_P1, RX_ADDR_P2, RX_ADDR_P3, RX_ADDR_P4, RX_ADDR_P5 +}; +static const uint8_t child_payload_size[] PROGMEM = +{ + RX_PW_P0, RX_PW_P1, RX_PW_P2, RX_PW_P3, RX_PW_P4, RX_PW_P5 +}; + + +void RF24::openReadingPipe(uint8_t child, uint64_t address) +{ + // If this is pipe 0, cache the address. This is needed because + // openWritingPipe() will overwrite the pipe 0 address, so + // startListening() will have to restore it. + if (child == 0){ + memcpy(pipe0_reading_address,&address,addr_width); + } + + if (child <= 6) + { + // For pipes 2-5, only write the LSB + if ( child < 2 ) + write_register(pgm_read_byte(&child_pipe[child]), reinterpret_cast(&address), addr_width); + else + write_register(pgm_read_byte(&child_pipe[child]), reinterpret_cast(&address), 1); + + write_register(pgm_read_byte(&child_payload_size[child]),payload_size); + + // Note it would be more efficient to set all of the bits for all open + // pipes at once. However, I thought it would make the calling code + // more simple to do it this way. + write_register(EN_RXADDR,read_register(EN_RXADDR) | _BV(pgm_read_byte(&child_pipe_enable[child]))); + } +} + +/****************************************************************************/ +void RF24::setAddressWidth(uint8_t a_width){ + + if(a_width -= 2){ + write_register(SETUP_AW,a_width%4); + addr_width = (a_width%4) + 2; + }else{ + write_register(SETUP_AW,0); + addr_width = 2; + } + +} + +/****************************************************************************/ + +void RF24::openReadingPipe(uint8_t child, const uint8_t *address) +{ + // If this is pipe 0, cache the address. This is needed because + // openWritingPipe() will overwrite the pipe 0 address, so + // startListening() will have to restore it. + if (child == 0){ + memcpy(pipe0_reading_address,address,addr_width); + } + if (child <= 6) + { + // For pipes 2-5, only write the LSB + if ( child < 2 ){ + write_register(pgm_read_byte(&child_pipe[child]), address, addr_width); + }else{ + write_register(pgm_read_byte(&child_pipe[child]), address, 1); + } + write_register(pgm_read_byte(&child_payload_size[child]),payload_size); + + // Note it would be more efficient to set all of the bits for all open + // pipes at once. However, I thought it would make the calling code + // more simple to do it this way. + write_register(EN_RXADDR,read_register(EN_RXADDR) | _BV(pgm_read_byte(&child_pipe_enable[child]))); + + } +} + +/****************************************************************************/ + +void RF24::closeReadingPipe( uint8_t pipe ) +{ + write_register(EN_RXADDR,read_register(EN_RXADDR) & ~_BV(pgm_read_byte(&child_pipe_enable[pipe]))); +} + +/****************************************************************************/ + +void RF24::toggle_features(void) +{ + beginTransaction(); + _SPI.transfer( ACTIVATE ); + _SPI.transfer( 0x73 ); + endTransaction(); +} + +/****************************************************************************/ + +void RF24::enableDynamicPayloads(void) +{ + // Enable dynamic payload throughout the system + + //toggle_features(); + write_register(FEATURE,read_register(FEATURE) | _BV(EN_DPL) ); + + + IF_SERIAL_DEBUG(printf("FEATURE=%i\r\n",read_register(FEATURE))); + + // Enable dynamic payload on all pipes + // + // Not sure the use case of only having dynamic payload on certain + // pipes, so the library does not support it. + write_register(DYNPD,read_register(DYNPD) | _BV(DPL_P5) | _BV(DPL_P4) | _BV(DPL_P3) | _BV(DPL_P2) | _BV(DPL_P1) | _BV(DPL_P0)); + + dynamic_payloads_enabled = true; +} + +/****************************************************************************/ +void RF24::disableDynamicPayloads(void) +{ + // Disables dynamic payload throughout the system. Also disables Ack Payloads + + //toggle_features(); + write_register(FEATURE, 0); + + + IF_SERIAL_DEBUG(printf("FEATURE=%i\r\n",read_register(FEATURE))); + + // Disable dynamic payload on all pipes + // + // Not sure the use case of only having dynamic payload on certain + // pipes, so the library does not support it. + write_register(DYNPD, 0); + + dynamic_payloads_enabled = false; +} + +/****************************************************************************/ + +void RF24::enableAckPayload(void) +{ + // + // enable ack payload and dynamic payload features + // + + //toggle_features(); + write_register(FEATURE,read_register(FEATURE) | _BV(EN_ACK_PAY) | _BV(EN_DPL) ); + + IF_SERIAL_DEBUG(printf("FEATURE=%i\r\n",read_register(FEATURE))); + + // + // Enable dynamic payload on pipes 0 & 1 + // + + write_register(DYNPD,read_register(DYNPD) | _BV(DPL_P1) | _BV(DPL_P0)); + dynamic_payloads_enabled = true; +} + +/****************************************************************************/ + +void RF24::enableDynamicAck(void){ + // + // enable dynamic ack features + // + //toggle_features(); + write_register(FEATURE,read_register(FEATURE) | _BV(EN_DYN_ACK) ); + + IF_SERIAL_DEBUG(printf("FEATURE=%i\r\n",read_register(FEATURE))); + + +} + +/****************************************************************************/ + +void RF24::writeAckPayload(uint8_t pipe, const void* buf, uint8_t len) +{ + const uint8_t* current = reinterpret_cast(buf); + + uint8_t data_len = rf24_min(len,32); + + #if defined (RF24_LINUX) + beginTransaction(); + uint8_t * ptx = spi_txbuff; + uint8_t size = data_len + 1 ; // Add register value to transmit buffer + *ptx++ = W_ACK_PAYLOAD | ( pipe & 0x07 ); + while ( data_len-- ){ + *ptx++ = *current++; + } + + _SPI.transfern( (char *) spi_txbuff, size); + endTransaction(); + #else + beginTransaction(); + _SPI.transfer(W_ACK_PAYLOAD | ( pipe & 0x07 ) ); + + while ( data_len-- ) + _SPI.transfer(*current++); + endTransaction(); + + #endif + +} + +/****************************************************************************/ + +bool RF24::isAckPayloadAvailable(void) +{ + return ! (read_register(FIFO_STATUS) & _BV(RX_EMPTY)); +} + +/****************************************************************************/ + +bool RF24::isPVariant(void) +{ + return p_variant ; +} + +/****************************************************************************/ + +void RF24::setAutoAck(bool enable) +{ + if ( enable ) + write_register(EN_AA, 0x3F); + else + write_register(EN_AA, 0); +} + +/****************************************************************************/ + +void RF24::setAutoAck( uint8_t pipe, bool enable ) +{ + if ( pipe <= 6 ) + { + uint8_t en_aa = read_register( EN_AA ) ; + if( enable ) + { + en_aa |= _BV(pipe) ; + } + else + { + en_aa &= ~_BV(pipe) ; + } + write_register( EN_AA, en_aa ) ; + } +} + +/****************************************************************************/ + +bool RF24::testCarrier(void) +{ + return ( read_register(CD) & 1 ); +} + +/****************************************************************************/ + +bool RF24::testRPD(void) +{ + return ( read_register(RPD) & 1 ) ; +} + +/****************************************************************************/ + +void RF24::setPALevel(uint8_t level) +{ + + uint8_t setup = read_register(RF_SETUP) & 0xF8; + + if(level > 3){ // If invalid level, go to max PA + level = (RF24_PA_MAX << 1) + 1; // +1 to support the SI24R1 chip extra bit + }else{ + level = (level << 1) + 1; // Else set level as requested + } + + + write_register( RF_SETUP, setup |= level ) ; // Write it to the chip +} + +/****************************************************************************/ + +uint8_t RF24::getPALevel(void) +{ + + return (read_register(RF_SETUP) & (_BV(RF_PWR_LOW) | _BV(RF_PWR_HIGH))) >> 1 ; +} + +/****************************************************************************/ + +bool RF24::setDataRate(rf24_datarate_e speed) +{ + bool result = false; + uint8_t setup = read_register(RF_SETUP) ; + + // HIGH and LOW '00' is 1Mbs - our default + setup &= ~(_BV(RF_DR_LOW) | _BV(RF_DR_HIGH)) ; + + #if defined(__arm__) || defined (RF24_LINUX) || defined (__ARDUINO_X86__) + txDelay=250; + #else //16Mhz Arduino + txDelay=85; + #endif + if( speed == RF24_250KBPS ) + { + // Must set the RF_DR_LOW to 1; RF_DR_HIGH (used to be RF_DR) is already 0 + // Making it '10'. + setup |= _BV( RF_DR_LOW ) ; + #if defined(__arm__) || defined (RF24_LINUX) || defined (__ARDUINO_X86__) + txDelay=450; + #else //16Mhz Arduino + txDelay=155; + #endif + } + else + { + // Set 2Mbs, RF_DR (RF_DR_HIGH) is set 1 + // Making it '01' + if ( speed == RF24_2MBPS ) + { + setup |= _BV(RF_DR_HIGH); + #if defined(__arm__) || defined (RF24_LINUX) || defined (__ARDUINO_X86__) + txDelay=190; + #else //16Mhz Arduino + txDelay=65; + #endif + } + } + write_register(RF_SETUP,setup); + + // Verify our result + if ( read_register(RF_SETUP) == setup ) + { + result = true; + } + return result; +} + +/****************************************************************************/ + +rf24_datarate_e RF24::getDataRate( void ) +{ + rf24_datarate_e result ; + uint8_t dr = read_register(RF_SETUP) & (_BV(RF_DR_LOW) | _BV(RF_DR_HIGH)); + + // switch uses RAM (evil!) + // Order matters in our case below + if ( dr == _BV(RF_DR_LOW) ) + { + // '10' = 250KBPS + result = RF24_250KBPS ; + } + else if ( dr == _BV(RF_DR_HIGH) ) + { + // '01' = 2MBPS + result = RF24_2MBPS ; + } + else + { + // '00' = 1MBPS + result = RF24_1MBPS ; + } + return result ; +} + +/****************************************************************************/ + +void RF24::setCRCLength(rf24_crclength_e length) +{ + uint8_t config = read_register(NRF_CONFIG) & ~( _BV(CRCO) | _BV(EN_CRC)) ; + + // switch uses RAM (evil!) + if ( length == RF24_CRC_DISABLED ) + { + // Do nothing, we turned it off above. + } + else if ( length == RF24_CRC_8 ) + { + config |= _BV(EN_CRC); + } + else + { + config |= _BV(EN_CRC); + config |= _BV( CRCO ); + } + write_register( NRF_CONFIG, config ) ; +} + +/****************************************************************************/ + +rf24_crclength_e RF24::getCRCLength(void) +{ + rf24_crclength_e result = RF24_CRC_DISABLED; + + uint8_t config = read_register(NRF_CONFIG) & ( _BV(CRCO) | _BV(EN_CRC)) ; + uint8_t AA = read_register(EN_AA); + + if ( config & _BV(EN_CRC ) || AA) + { + if ( config & _BV(CRCO) ) + result = RF24_CRC_16; + else + result = RF24_CRC_8; + } + + return result; +} + +/****************************************************************************/ + +void RF24::disableCRC( void ) +{ + uint8_t disable = read_register(NRF_CONFIG) & ~_BV(EN_CRC) ; + write_register( NRF_CONFIG, disable ) ; +} + +/****************************************************************************/ +void RF24::setRetries(uint8_t delay, uint8_t count) +{ + write_register(SETUP_RETR,(delay&0xf)< + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + */ + +/** + * @file RF24.h + * + * Class declaration for RF24 and helper enums + */ + +#ifndef __RF24_H__ +#define __RF24_H__ + +#include "RF24_config.h" + +#if defined (RF24_LINUX) || defined (LITTLEWIRE) + #include "utility/includes.h" +#elif defined SOFTSPI + #include +#endif + +/** + * Power Amplifier level. + * + * For use with setPALevel() + */ +typedef enum { RF24_PA_MIN = 0,RF24_PA_LOW, RF24_PA_HIGH, RF24_PA_MAX, RF24_PA_ERROR } rf24_pa_dbm_e ; + +/** + * Data rate. How fast data moves through the air. + * + * For use with setDataRate() + */ +typedef enum { RF24_1MBPS = 0, RF24_2MBPS, RF24_250KBPS } rf24_datarate_e; + +/** + * CRC Length. How big (if any) of a CRC is included. + * + * For use with setCRCLength() + */ +typedef enum { RF24_CRC_DISABLED = 0, RF24_CRC_8, RF24_CRC_16 } rf24_crclength_e; + +/** + * Driver for nRF24L01(+) 2.4GHz Wireless Transceiver + */ + +class RF24 +{ +private: +#ifdef SOFTSPI + SoftSPI spi; +#elif defined (SPI_UART) + SPIUARTClass uspi; +#endif + +#if defined (RF24_LINUX) || defined (XMEGA_D3) /* XMEGA can use SPI class */ + SPI spi; +#endif +#if defined (MRAA) + GPIO gpio; +#endif + + uint16_t ce_pin; /**< "Chip Enable" pin, activates the RX or TX role */ + uint16_t csn_pin; /**< SPI Chip select */ + uint16_t spi_speed; /**< SPI Bus Speed */ +#if defined (RF24_LINUX) || defined (XMEGA_D3) + uint8_t spi_rxbuff[32+1] ; //SPI receive buffer (payload max 32 bytes) + uint8_t spi_txbuff[32+1] ; //SPI transmit buffer (payload max 32 bytes + 1 byte for the command) +#endif + bool p_variant; /* False for RF24L01 and true for RF24L01P */ + uint8_t payload_size; /**< Fixed size of payloads */ + bool dynamic_payloads_enabled; /**< Whether dynamic payloads are enabled. */ + uint8_t pipe0_reading_address[5]; /**< Last address set on pipe 0 for reading. */ + uint8_t addr_width; /**< The address width to use - 3,4 or 5 bytes. */ + + +protected: + /** + * SPI transactions + * + * Common code for SPI transactions including CSN toggle + * + */ + inline void beginTransaction(); + + inline void endTransaction(); + +public: + + /** + * @name Primary public interface + * + * These are the main methods you need to operate the chip + */ + /**@{*/ + + /** + * Arduino Constructor + * + * Creates a new instance of this driver. Before using, you create an instance + * and send in the unique pins that this chip is connected to. + * + * @param _cepin The pin attached to Chip Enable on the RF module + * @param _cspin The pin attached to Chip Select + */ + RF24(uint16_t _cepin, uint16_t _cspin); + //#if defined (RF24_LINUX) + + /** + * Optional Linux Constructor + * + * Creates a new instance of this driver. Before using, you create an instance + * and send in the unique pins that this chip is connected to. + * + * @param _cepin The pin attached to Chip Enable on the RF module + * @param _cspin The pin attached to Chip Select + * @param spispeed For RPi, the SPI speed in MHZ ie: BCM2835_SPI_SPEED_8MHZ + */ + + RF24(uint16_t _cepin, uint16_t _cspin, uint32_t spispeed ); + //#endif + + #if defined (RF24_LINUX) + virtual ~RF24() {}; + #endif + + /** + * Begin operation of the chip + * + * Call this in setup(), before calling any other methods. + * @code radio.begin() @endcode + */ + bool begin(void); + + /** + * Checks if the chip is connected to the SPI bus + */ + bool isChipConnected(); + + /** + * Start listening on the pipes opened for reading. + * + * 1. Be sure to call openReadingPipe() first. + * 2. Do not call write() while in this mode, without first calling stopListening(). + * 3. Call available() to check for incoming traffic, and read() to get it. + * + * @code + * Open reading pipe 1 using address CCCECCCECC + * + * byte address[] = { 0xCC,0xCE,0xCC,0xCE,0xCC }; + * radio.openReadingPipe(1,address); + * radio.startListening(); + * @endcode + */ + void startListening(void); + + /** + * Stop listening for incoming messages, and switch to transmit mode. + * + * Do this before calling write(). + * @code + * radio.stopListening(); + * radio.write(&data,sizeof(data)); + * @endcode + */ + void stopListening(void); + + /** + * Check whether there are bytes available to be read + * @code + * if(radio.available()){ + * radio.read(&data,sizeof(data)); + * } + * @endcode + * @return True if there is a payload available, false if none is + */ + bool available(void); + + /** + * Read the available payload + * + * The size of data read is the fixed payload size, see getPayloadSize() + * + * @note I specifically chose 'void*' as a data type to make it easier + * for beginners to use. No casting needed. + * + * @note No longer boolean. Use available to determine if packets are + * available. Interrupt flags are now cleared during reads instead of + * when calling available(). + * + * @param buf Pointer to a buffer where the data should be written + * @param len Maximum number of bytes to read into the buffer + * + * @code + * if(radio.available()){ + * radio.read(&data,sizeof(data)); + * } + * @endcode + * @return No return value. Use available(). + */ + void read( void* buf, uint8_t len ); + + /** + * Be sure to call openWritingPipe() first to set the destination + * of where to write to. + * + * This blocks until the message is successfully acknowledged by + * the receiver or the timeout/retransmit maxima are reached. In + * the current configuration, the max delay here is 60-70ms. + * + * The maximum size of data written is the fixed payload size, see + * getPayloadSize(). However, you can write less, and the remainder + * will just be filled with zeroes. + * + * TX/RX/RT interrupt flags will be cleared every time write is called + * + * @param buf Pointer to the data to be sent + * @param len Number of bytes to be sent + * + * @code + * radio.stopListening(); + * radio.write(&data,sizeof(data)); + * @endcode + * @return True if the payload was delivered successfully false if not + */ + bool write( const void* buf, uint8_t len ); + + /** + * New: Open a pipe for writing via byte array. Old addressing format retained + * for compatibility. + * + * Only one writing pipe can be open at once, but you can change the address + * you'll write to. Call stopListening() first. + * + * Addresses are assigned via a byte array, default is 5 byte address length +s * + * @code + * uint8_t addresses[][6] = {"1Node","2Node"}; + * radio.openWritingPipe(addresses[0]); + * @endcode + * @code + * uint8_t address[] = { 0xCC,0xCE,0xCC,0xCE,0xCC }; + * radio.openWritingPipe(address); + * address[0] = 0x33; + * radio.openReadingPipe(1,address); + * @endcode + * @see setAddressWidth + * + * @param address The address of the pipe to open. Coordinate these pipe + * addresses amongst nodes on the network. + */ + + void openWritingPipe(const uint8_t *address); +void openWritingPipe(const uint8_t *address,int len ); + /** + * Open a pipe for reading + * + * Up to 6 pipes can be open for reading at once. Open all the required + * reading pipes, and then call startListening(). + * + * @see openWritingPipe + * @see setAddressWidth + * + * @note Pipes 0 and 1 will store a full 5-byte address. Pipes 2-5 will technically + * only store a single byte, borrowing up to 4 additional bytes from pipe #1 per the + * assigned address width. + * @warning Pipes 1-5 should share the same address, except the first byte. + * Only the first byte in the array should be unique, e.g. + * @code + * uint8_t addresses[][6] = {"1Node","2Node"}; + * openReadingPipe(1,addresses[0]); + * openReadingPipe(2,addresses[1]); + * @endcode + * + * @warning Pipe 0 is also used by the writing pipe. So if you open + * pipe 0 for reading, and then startListening(), it will overwrite the + * writing pipe. Ergo, do an openWritingPipe() again before write(). + * + * @param number Which pipe# to open, 0-5. + * @param address The 24, 32 or 40 bit address of the pipe to open. + */ + + void openReadingPipe(uint8_t number, const uint8_t *address); + + /**@}*/ + /** + * @name Advanced Operation + * + * Methods you can use to drive the chip in more advanced ways + */ + /**@{*/ + + /** + * Print a giant block of debugging information to stdout + * + * @warning Does nothing if stdout is not defined. See fdevopen in stdio.h + * The printf.h file is included with the library for Arduino. + * @code + * #include + * setup(){ + * Serial.begin(115200); + * printf_begin(); + * ... + * } + * @endcode + */ + void printDetails(void); + + void print_config(void); + /** + * Test whether there are bytes available to be read in the + * FIFO buffers. + * + * @param[out] pipe_num Which pipe has the payload available + * + * @code + * uint8_t pipeNum; + * if(radio.available(&pipeNum)){ + * radio.read(&data,sizeof(data)); + * Serial.print("Got data on pipe"); + * Serial.println(pipeNum); + * } + * @endcode + * @return True if there is a payload available, false if none is + */ + bool available(uint8_t* pipe_num); + + /** + * Check if the radio needs to be read. Can be used to prevent data loss + * @return True if all three 32-byte radio buffers are full + */ + bool rxFifoFull(); + + /** + * Enter low-power mode + * + * To return to normal power mode, call powerUp(). + * + * @note After calling startListening(), a basic radio will consume about 13.5mA + * at max PA level. + * During active transmission, the radio will consume about 11.5mA, but this will + * be reduced to 26uA (.026mA) between sending. + * In full powerDown mode, the radio will consume approximately 900nA (.0009mA) + * + * @code + * radio.powerDown(); + * avr_enter_sleep_mode(); // Custom function to sleep the device + * radio.powerUp(); + * @endcode + */ + void powerDown(void); + + /** + * Leave low-power mode - required for normal radio operation after calling powerDown() + * + * To return to low power mode, call powerDown(). + * @note This will take up to 5ms for maximum compatibility + */ + void powerUp(void) ; + + /** + * Write for single NOACK writes. Optionally disables acknowledgements/autoretries for a single write. + * + * @note enableDynamicAck() must be called to enable this feature + * + * Can be used with enableAckPayload() to request a response + * @see enableDynamicAck() + * @see setAutoAck() + * @see write() + * + * @param buf Pointer to the data to be sent + * @param len Number of bytes to be sent + * @param multicast Request ACK (0), NOACK (1) + */ + bool write( const void* buf, uint8_t len, const bool multicast ); + + /** + * This will not block until the 3 FIFO buffers are filled with data. + * Once the FIFOs are full, writeFast will simply wait for success or + * timeout, and return 1 or 0 respectively. From a user perspective, just + * keep trying to send the same data. The library will keep auto retrying + * the current payload using the built in functionality. + * @warning It is important to never keep the nRF24L01 in TX mode and FIFO full for more than 4ms at a time. If the auto + * retransmit is enabled, the nRF24L01 is never in TX mode long enough to disobey this rule. Allow the FIFO + * to clear by issuing txStandBy() or ensure appropriate time between transmissions. + * + * @code + * Example (Partial blocking): + * + * radio.writeFast(&buf,32); // Writes 1 payload to the buffers + * txStandBy(); // Returns 0 if failed. 1 if success. Blocks only until MAX_RT timeout or success. Data flushed on fail. + * + * radio.writeFast(&buf,32); // Writes 1 payload to the buffers + * txStandBy(1000); // Using extended timeouts, returns 1 if success. Retries failed payloads for 1 seconds before returning 0. + * @endcode + * + * @see txStandBy() + * @see write() + * @see writeBlocking() + * + * @param buf Pointer to the data to be sent + * @param len Number of bytes to be sent + * @return True if the payload was delivered successfully false if not + */ + bool writeFast( const void* buf, uint8_t len ); + + /** + * WriteFast for single NOACK writes. Disables acknowledgements/autoretries for a single write. + * + * @note enableDynamicAck() must be called to enable this feature + * @see enableDynamicAck() + * @see setAutoAck() + * + * @param buf Pointer to the data to be sent + * @param len Number of bytes to be sent + * @param multicast Request ACK (0) or NOACK (1) + */ + bool writeFast( const void* buf, uint8_t len, const bool multicast ); + + /** + * This function extends the auto-retry mechanism to any specified duration. + * It will not block until the 3 FIFO buffers are filled with data. + * If so the library will auto retry until a new payload is written + * or the user specified timeout period is reached. + * @warning It is important to never keep the nRF24L01 in TX mode and FIFO full for more than 4ms at a time. If the auto + * retransmit is enabled, the nRF24L01 is never in TX mode long enough to disobey this rule. Allow the FIFO + * to clear by issuing txStandBy() or ensure appropriate time between transmissions. + * + * @code + * Example (Full blocking): + * + * radio.writeBlocking(&buf,32,1000); //Wait up to 1 second to write 1 payload to the buffers + * txStandBy(1000); //Wait up to 1 second for the payload to send. Return 1 if ok, 0 if failed. + * //Blocks only until user timeout or success. Data flushed on fail. + * @endcode + * @note If used from within an interrupt, the interrupt should be disabled until completion, and sei(); called to enable millis(). + * @see txStandBy() + * @see write() + * @see writeFast() + * + * @param buf Pointer to the data to be sent + * @param len Number of bytes to be sent + * @param timeout User defined timeout in milliseconds. + * @return True if the payload was loaded into the buffer successfully false if not + */ + bool writeBlocking( const void* buf, uint8_t len, uint32_t timeout ); + + /** + * This function should be called as soon as transmission is finished to + * drop the radio back to STANDBY-I mode. If not issued, the radio will + * remain in STANDBY-II mode which, per the data sheet, is not a recommended + * operating mode. + * + * @note When transmitting data in rapid succession, it is still recommended by + * the manufacturer to drop the radio out of TX or STANDBY-II mode if there is + * time enough between sends for the FIFOs to empty. This is not required if auto-ack + * is enabled. + * + * Relies on built-in auto retry functionality. + * + * @code + * Example (Partial blocking): + * + * radio.writeFast(&buf,32); + * radio.writeFast(&buf,32); + * radio.writeFast(&buf,32); //Fills the FIFO buffers up + * bool ok = txStandBy(); //Returns 0 if failed. 1 if success. + * //Blocks only until MAX_RT timeout or success. Data flushed on fail. + * @endcode + * @see txStandBy(unsigned long timeout) + * @return True if transmission is successful + * + */ + bool txStandBy(); + + /** + * This function allows extended blocking and auto-retries per a user defined timeout + * @code + * Fully Blocking Example: + * + * radio.writeFast(&buf,32); + * radio.writeFast(&buf,32); + * radio.writeFast(&buf,32); //Fills the FIFO buffers up + * bool ok = txStandBy(1000); //Returns 0 if failed after 1 second of retries. 1 if success. + * //Blocks only until user defined timeout or success. Data flushed on fail. + * @endcode + * @note If used from within an interrupt, the interrupt should be disabled until completion, and sei(); called to enable millis(). + * @param timeout Number of milliseconds to retry failed payloads + * @return True if transmission is successful + * + */ + bool txStandBy(uint32_t timeout, bool startTx = 0); + + /** + * Write an ack payload for the specified pipe + * + * The next time a message is received on @p pipe, the data in @p buf will + * be sent back in the acknowledgement. + * @see enableAckPayload() + * @see enableDynamicPayloads() + * @warning Only three of these can be pending at any time as there are only 3 FIFO buffers.
Dynamic payloads must be enabled. + * @note Ack payloads are handled automatically by the radio chip when a payload is received. Users should generally + * write an ack payload as soon as startListening() is called, so one is available when a regular payload is received. + * @note Ack payloads are dynamic payloads. This only works on pipes 0&1 by default. Call + * enableDynamicPayloads() to enable on all pipes. + * + * @param pipe Which pipe# (typically 1-5) will get this response. + * @param buf Pointer to data that is sent + * @param len Length of the data to send, up to 32 bytes max. Not affected + * by the static payload set by setPayloadSize(). + */ + void writeAckPayload(uint8_t pipe, const void* buf, uint8_t len); + + /** + * Determine if an ack payload was received in the most recent call to + * write(). The regular available() can also be used. + * + * Call read() to retrieve the ack payload. + * + * @return True if an ack payload is available. + */ + bool isAckPayloadAvailable(void); + + /** + * Call this when you get an interrupt to find out why + * + * Tells you what caused the interrupt, and clears the state of + * interrupts. + * + * @param[out] tx_ok The send was successful (TX_DS) + * @param[out] tx_fail The send failed, too many retries (MAX_RT) + * @param[out] rx_ready There is a message waiting to be read (RX_DS) + */ + void whatHappened(bool& tx_ok,bool& tx_fail,bool& rx_ready); + + /** + * Non-blocking write to the open writing pipe used for buffered writes + * + * @note Optimization: This function now leaves the CE pin high, so the radio + * will remain in TX or STANDBY-II Mode until a txStandBy() command is issued. Can be used as an alternative to startWrite() + * if writing multiple payloads at once. + * @warning It is important to never keep the nRF24L01 in TX mode with FIFO full for more than 4ms at a time. If the auto + * retransmit/autoAck is enabled, the nRF24L01 is never in TX mode long enough to disobey this rule. Allow the FIFO + * to clear by issuing txStandBy() or ensure appropriate time between transmissions. + * + * @see write() + * @see writeFast() + * @see startWrite() + * @see writeBlocking() + * + * For single noAck writes see: + * @see enableDynamicAck() + * @see setAutoAck() + * + * @param buf Pointer to the data to be sent + * @param len Number of bytes to be sent + * @param multicast Request ACK (0) or NOACK (1) + * @return True if the payload was delivered successfully false if not + */ + void startFastWrite( const void* buf, uint8_t len, const bool multicast, bool startTx = 1 ); + + /** + * Non-blocking write to the open writing pipe + * + * Just like write(), but it returns immediately. To find out what happened + * to the send, catch the IRQ and then call whatHappened(). + * + * @see write() + * @see writeFast() + * @see startFastWrite() + * @see whatHappened() + * + * For single noAck writes see: + * @see enableDynamicAck() + * @see setAutoAck() + * + * @param buf Pointer to the data to be sent + * @param len Number of bytes to be sent + * @param multicast Request ACK (0) or NOACK (1) + * + */ + void startWrite( const void* buf, uint8_t len, const bool multicast ); + + /** + * This function is mainly used internally to take advantage of the auto payload + * re-use functionality of the chip, but can be beneficial to users as well. + * + * The function will instruct the radio to re-use the data in the FIFO buffers, + * and instructs the radio to re-send once the timeout limit has been reached. + * Used by writeFast and writeBlocking to initiate retries when a TX failure + * occurs. Retries are automatically initiated except with the standard write(). + * This way, data is not flushed from the buffer until switching between modes. + * + * @note This is to be used AFTER auto-retry fails if wanting to resend + * using the built-in payload reuse features. + * After issuing reUseTX(), it will keep reending the same payload forever or until + * a payload is written to the FIFO, or a flush_tx command is given. + */ + void reUseTX(); + + /** + * Empty the transmit buffer. This is generally not required in standard operation. + * May be required in specific cases after stopListening() , if operating at 250KBPS data rate. + * + * @return Current value of status register + */ + uint8_t flush_tx(void); + + /** + * Test whether there was a carrier on the line for the + * previous listening period. + * + * Useful to check for interference on the current channel. + * + * @return true if was carrier, false if not + */ + bool testCarrier(void); + + /** + * Test whether a signal (carrier or otherwise) greater than + * or equal to -64dBm is present on the channel. Valid only + * on nRF24L01P (+) hardware. On nRF24L01, use testCarrier(). + * + * Useful to check for interference on the current channel and + * channel hopping strategies. + * + * @code + * bool goodSignal = radio.testRPD(); + * if(radio.available()){ + * Serial.println(goodSignal ? "Strong signal > 64dBm" : "Weak signal < 64dBm" ); + * radio.read(0,0); + * } + * @endcode + * @return true if signal => -64dBm, false if not + */ + bool testRPD(void) ; + + /** + * Test whether this is a real radio, or a mock shim for + * debugging. Setting either pin to 0xff is the way to + * indicate that this is not a real radio. + * + * @return true if this is a legitimate radio + */ + bool isValid() { return ce_pin != 0xff && csn_pin != 0xff; } + + /** + * Close a pipe after it has been previously opened. + * Can be safely called without having previously opened a pipe. + * @param pipe Which pipe # to close, 0-5. + */ + void closeReadingPipe( uint8_t pipe ) ; + + /** + * Enable error detection by un-commenting #define FAILURE_HANDLING in RF24_config.h + * If a failure has been detected, it usually indicates a hardware issue. By default the library + * will cease operation when a failure is detected. + * This should allow advanced users to detect and resolve intermittent hardware issues. + * + * In most cases, the radio must be re-enabled via radio.begin(); and the appropriate settings + * applied after a failure occurs, if wanting to re-enable the device immediately. + * + * Usage: (Failure handling must be enabled per above) + * @code + * if(radio.failureDetected){ + * radio.begin(); // Attempt to re-configure the radio with defaults + * radio.failureDetected = 0; // Reset the detection value + * radio.openWritingPipe(addresses[1]); // Re-configure pipe addresses + * radio.openReadingPipe(1,addresses[0]); + * report_failure(); // Blink leds, send a message, etc. to indicate failure + * } + * @endcode + */ + //#if defined (FAILURE_HANDLING) + bool failureDetected; + //#endif + + /**@}*/ + + /**@}*/ + /** + * @name Optional Configurators + * + * Methods you can use to get or set the configuration of the chip. + * None are required. Calling begin() sets up a reasonable set of + * defaults. + */ + /**@{*/ + + /** + * Set the address width from 3 to 5 bytes (24, 32 or 40 bit) + * + * @param a_width The address width to use: 3,4 or 5 + */ + + void setAddressWidth(uint8_t a_width); + + /** + * Set the number and delay of retries upon failed submit + * + * @param delay How long to wait between each retry, in multiples of 250us, + * max is 15. 0 means 250us, 15 means 4000us. + * @param count How many retries before giving up, max 15 + */ + void setRetries(uint8_t delay, uint8_t count); + + /** + * Set RF communication channel + * + * @param channel Which RF channel to communicate on, 0-125 + */ + void setChannel(uint8_t channel); + + /** + * Get RF communication channel + * + * @return The currently configured RF Channel + */ + uint8_t getChannel(void); + + /** + * Set Static Payload Size + * + * This implementation uses a pre-stablished fixed payload size for all + * transmissions. If this method is never called, the driver will always + * transmit the maximum payload size (32 bytes), no matter how much + * was sent to write(). + * + * @todo Implement variable-sized payloads feature + * + * @param size The number of bytes in the payload + */ + void setPayloadSize(uint8_t size); + + /** + * Get Static Payload Size + * + * @see setPayloadSize() + * + * @return The number of bytes in the payload + */ + uint8_t getPayloadSize(void); + + /** + * Get Dynamic Payload Size + * + * For dynamic payloads, this pulls the size of the payload off + * the chip + * + * @note Corrupt packets are now detected and flushed per the + * manufacturer. + * @code + * if(radio.available()){ + * if(radio.getDynamicPayloadSize() < 1){ + * // Corrupt payload has been flushed + * return; + * } + * radio.read(&data,sizeof(data)); + * } + * @endcode + * + * @return Payload length of last-received dynamic payload + */ + uint8_t getDynamicPayloadSize(void); + + /** + * Enable custom payloads on the acknowledge packets + * + * Ack payloads are a handy way to return data back to senders without + * manually changing the radio modes on both units. + * + * @note Ack payloads are dynamic payloads. This only works on pipes 0&1 by default. Call + * enableDynamicPayloads() to enable on all pipes. + */ + void enableAckPayload(void); + + /** + * Enable dynamically-sized payloads + * + * This way you don't always have to send large packets just to send them + * once in a while. This enables dynamic payloads on ALL pipes. + * + */ + void enableDynamicPayloads(void); + + /** + * Disable dynamically-sized payloads + * + * This disables dynamic payloads on ALL pipes. Since Ack Payloads + * requires Dynamic Payloads, Ack Payloads are also disabled. + * If dynamic payloads are later re-enabled and ack payloads are desired + * then enableAckPayload() must be called again as well. + * + */ + void disableDynamicPayloads(void); + + /** + * Enable dynamic ACKs (single write multicast or unicast) for chosen messages + * + * @note To enable full multicast or per-pipe multicast, use setAutoAck() + * + * @warning This MUST be called prior to attempting single write NOACK calls + * @code + * radio.enableDynamicAck(); + * radio.write(&data,32,1); // Sends a payload with no acknowledgement requested + * radio.write(&data,32,0); // Sends a payload using auto-retry/autoACK + * @endcode + */ + void enableDynamicAck(); + + /** + * Determine whether the hardware is an nRF24L01+ or not. + * + * @return true if the hardware is nRF24L01+ (or compatible) and false + * if its not. + */ + bool isPVariant(void) ; + + /** + * Enable or disable auto-acknowlede packets + * + * This is enabled by default, so it's only needed if you want to turn + * it off for some reason. + * + * @param enable Whether to enable (true) or disable (false) auto-acks + */ + void setAutoAck(bool enable); + + /** + * Enable or disable auto-acknowlede packets on a per pipeline basis. + * + * AA is enabled by default, so it's only needed if you want to turn + * it off/on for some reason on a per pipeline basis. + * + * @param pipe Which pipeline to modify + * @param enable Whether to enable (true) or disable (false) auto-acks + */ + void setAutoAck( uint8_t pipe, bool enable ) ; + + /** + * Set Power Amplifier (PA) level to one of four levels: + * RF24_PA_MIN, RF24_PA_LOW, RF24_PA_HIGH and RF24_PA_MAX + * + * The power levels correspond to the following output levels respectively: + * NRF24L01: -18dBm, -12dBm,-6dBM, and 0dBm + * + * SI24R1: -6dBm, 0dBm, 3dBM, and 7dBm. + * + * @param level Desired PA level. + */ + void setPALevel ( uint8_t level ); + + /** + * Fetches the current PA level. + * + * NRF24L01: -18dBm, -12dBm, -6dBm and 0dBm + * SI24R1: -6dBm, 0dBm, 3dBm, 7dBm + * + * @return Returns values 0 to 3 representing the PA Level. + */ + uint8_t getPALevel( void ); + + /** + * Set the transmission data rate + * + * @warning setting RF24_250KBPS will fail for non-plus units + * + * @param speed RF24_250KBPS for 250kbs, RF24_1MBPS for 1Mbps, or RF24_2MBPS for 2Mbps + * @return true if the change was successful + */ + bool setDataRate(rf24_datarate_e speed); + + /** + * Fetches the transmission data rate + * + * @return Returns the hardware's currently configured datarate. The value + * is one of 250kbs, RF24_1MBPS for 1Mbps, or RF24_2MBPS, as defined in the + * rf24_datarate_e enum. + */ + rf24_datarate_e getDataRate( void ) ; + + /** + * Set the CRC length + *
CRC checking cannot be disabled if auto-ack is enabled + * @param length RF24_CRC_8 for 8-bit or RF24_CRC_16 for 16-bit + */ + void setCRCLength(rf24_crclength_e length); + + /** + * Get the CRC length + *
CRC checking cannot be disabled if auto-ack is enabled + * @return RF24_CRC_DISABLED if disabled or RF24_CRC_8 for 8-bit or RF24_CRC_16 for 16-bit + */ + rf24_crclength_e getCRCLength(void); + + /** + * Disable CRC validation + * + * @warning CRC cannot be disabled if auto-ack/ESB is enabled. + */ + void disableCRC( void ) ; + + /** + * The radio will generate interrupt signals when a transmission is complete, + * a transmission fails, or a payload is received. This allows users to mask + * those interrupts to prevent them from generating a signal on the interrupt + * pin. Interrupts are enabled on the radio chip by default. + * + * @code + * Mask all interrupts except the receive interrupt: + * + * radio.maskIRQ(1,1,0); + * @endcode + * + * @param tx_ok Mask transmission complete interrupts + * @param tx_fail Mask transmit failure interrupts + * @param rx_ready Mask payload received interrupts + */ + void maskIRQ(bool tx_ok,bool tx_fail,bool rx_ready); + + /** + * + * The driver will delay for this duration when stopListening() is called + * + * When responding to payloads, faster devices like ARM(RPi) are much faster than Arduino: + * 1. Arduino sends data to RPi, switches to RX mode + * 2. The RPi receives the data, switches to TX mode and sends before the Arduino radio is in RX mode + * 3. If AutoACK is disabled, this can be set as low as 0. If AA/ESB enabled, set to 100uS minimum on RPi + * + * @warning If set to 0, ensure 130uS delay after stopListening() and before any sends + */ + + uint32_t txDelay; + + /** + * + * On all devices but Linux and ATTiny, a small delay is added to the CSN toggling function + * + * This is intended to minimise the speed of SPI polling due to radio commands + * + * If using interrupts or timed requests, this can be set to 0 Default:5 + */ + + uint32_t csDelay; + + /**@}*/ + /** + * @name Deprecated + * + * Methods provided for backwards compabibility. + */ + /**@{*/ + + + /** + * Open a pipe for reading + * @note For compatibility with old code only, see new function + * + * @warning Pipes 1-5 should share the first 32 bits. + * Only the least significant byte should be unique, e.g. + * @code + * openReadingPipe(1,0xF0F0F0F0AA); + * openReadingPipe(2,0xF0F0F0F066); + * @endcode + * + * @warning Pipe 0 is also used by the writing pipe. So if you open + * pipe 0 for reading, and then startListening(), it will overwrite the + * writing pipe. Ergo, do an openWritingPipe() again before write(). + * + * @param number Which pipe# to open, 0-5. + * @param address The 40-bit address of the pipe to open. + */ + void openReadingPipe(uint8_t number, uint64_t address); + + /** + * Open a pipe for writing + * @note For compatibility with old code only, see new function + * + * Addresses are 40-bit hex values, e.g.: + * + * @code + * openWritingPipe(0xF0F0F0F0F0); + * @endcode + * + * @param address The 40-bit address of the pipe to open. + */ + void openWritingPipe(uint64_t address); + + /** + * Empty the receive buffer + * + * @return Current value of status register + */ + uint8_t flush_rx(void); + uint8_t Reader(void* buf); + uint8_t write_register(uint8_t reg, uint8_t value); + +private: + + /** + * @name Low-level internal interface. + * + * Protected methods that address the chip directly. Regular users cannot + * ever call these. They are documented for completeness and for developers who + * may want to extend this class. + */ + /**@{*/ + + /** + * Set chip select pin + * + * Running SPI bus at PI_CLOCK_DIV2 so we don't waste time transferring data + * and best of all, we make use of the radio's FIFO buffers. A lower speed + * means we're less likely to effectively leverage our FIFOs and pay a higher + * AVR runtime cost as toll. + * + * @param mode HIGH to take this unit off the SPI bus, LOW to put it on + */ + void csn(bool mode); + + /** + * Set chip enable + * + * @param level HIGH to actively begin transmission or LOW to put in standby. Please see data sheet + * for a much more detailed description of this pin. + */ + void ce(bool level); + + /** + * Read a chunk of data in from a register + * + * @param reg Which register. Use constants from nRF24L01.h + * @param buf Where to put the data + * @param len How many bytes of data to transfer + * @return Current value of status register + */ + uint8_t read_register(uint8_t reg, uint8_t* buf, uint8_t len); + + /** + * Read single byte from a register + * + * @param reg Which register. Use constants from nRF24L01.h + * @return Current value of register @p reg + */ + uint8_t read_register(uint8_t reg); + + /** + * Write a chunk of data to a register + * + * @param reg Which register. Use constants from nRF24L01.h + * @param buf Where to get the data + * @param len How many bytes of data to transfer + * @return Current value of status register + */ + uint8_t write_register(uint8_t reg, const uint8_t* buf, uint8_t len); + + /** + * Write a single byte to a register + * + * @param reg Which register. Use constants from nRF24L01.h + * @param value The new value to write + * @return Current value of status register + */ + + + /** + * Write the transmit payload + * + * The size of data written is the fixed payload size, see getPayloadSize() + * + * @param buf Where to get the data + * @param len Number of bytes to be sent + * @return Current value of status register + */ + uint8_t write_payload(const void* buf, uint8_t len, const uint8_t writeType); + + /** + * Read the receive payload + * + * The size of data read is the fixed payload size, see getPayloadSize() + * + * @param buf Where to put the data + * @param len Maximum number of bytes to read + * @return Current value of status register + */ + uint8_t read_payload(void* buf, uint8_t len); + + /** + * Retrieve the current status of the chip + * + * @return Current value of status register + */ + uint8_t get_status(void); + + #if !defined (MINIMAL) + /** + * Decode and print the given status to stdout + * + * @param status Status value to print + * + * @warning Does nothing if stdout is not defined. See fdevopen in stdio.h + */ + void print_status(uint8_t status); + + /** + * Decode and print the given 'observe_tx' value to stdout + * + * @param value The observe_tx value to print + * + * @warning Does nothing if stdout is not defined. See fdevopen in stdio.h + */ + void print_observe_tx(uint8_t value); + + /** + * Print the name and value of an 8-bit register to stdout + * + * Optionally it can print some quantity of successive + * registers on the same line. This is useful for printing a group + * of related registers on one line. + * + * @param name Name of the register + * @param reg Which register. Use constants from nRF24L01.h + * @param qty How many successive registers to print + */ + void print_byte_register(const char* name, uint8_t reg, uint8_t qty = 1); + + /** + * Print the name and value of a 40-bit address register to stdout + * + * Optionally it can print some quantity of successive + * registers on the same line. This is useful for printing a group + * of related registers on one line. + * + * @param name Name of the register + * @param reg Which register. Use constants from nRF24L01.h + * @param qty How many successive registers to print + */ + void print_address_register(const char* name, uint8_t reg, uint8_t qty = 1); +#endif + /** + * Turn on or off the special features of the chip + * + * The chip has certain 'features' which are only available when the 'features' + * are enabled. See the datasheet for details. + */ + void toggle_features(void); + + /** + * Built in spi transfer function to simplify repeating code repeating code + */ + + uint8_t spiTrans(uint8_t cmd); + + #if defined (FAILURE_HANDLING) || defined (RF24_LINUX) + void errNotify(void); + #endif + + /**@}*/ + +}; + + +/** + * @example GettingStarted.ino + * For Arduino
+ * Updated: TMRh20 2014
+ * + * This is an example of how to use the RF24 class to communicate on a basic level. Configure and write this sketch to two + * different nodes. Put one of the nodes into 'transmit' mode by connecting with the serial monitor and
+ * sending a 'T'. The ping node sends the current time to the pong node, which responds by sending the value + * back. The ping node can then see how long the whole cycle took.
+ * @note For a more efficient call-response scenario see the GettingStarted_CallResponse.ino example. + * @note When switching between sketches, the radio may need to be powered down to clear settings that are not "un-set" otherwise + */ + + /** + * @example gettingstarted.cpp + * For Linux
+ * Updated: TMRh20 2014
+ * + * This is an example of how to use the RF24 class to communicate on a basic level. Configure and write this sketch to two + * different nodes. Put one of the nodes into 'transmit' mode by connecting with the serial monitor and
+ * sending a 'T'. The ping node sends the current time to the pong node, which responds by sending the value + * back. The ping node can then see how long the whole cycle took.
+ * @note For a more efficient call-response scenario see the GettingStarted_CallResponse.ino example. + */ + +/** + * @example GettingStarted_CallResponse.ino + * For Arduino
+ * New: TMRh20 2014
+ * + * This example continues to make use of all the normal functionality of the radios including + * the auto-ack and auto-retry features, but allows ack-payloads to be written optionlly as well.
+ * This allows very fast call-response communication, with the responding radio never having to + * switch out of Primary Receiver mode to send back a payload, but having the option to switch to
+ * primary transmitter if wanting to initiate communication instead of respond to a commmunication. + */ + + /** + * @example gettingstarted_call_response.cpp + * For Linux
+ * New: TMRh20 2014
+ * + * This example continues to make use of all the normal functionality of the radios including + * the auto-ack and auto-retry features, but allows ack-payloads to be written optionlly as well.
+ * This allows very fast call-response communication, with the responding radio never having to + * switch out of Primary Receiver mode to send back a payload, but having the option to switch to
+ * primary transmitter if wanting to initiate communication instead of respond to a commmunication. + */ + + /** + * @example GettingStarted_HandlingData.ino + * Dec 2014 - TMRh20
+ * + * This example demonstrates how to send multiple variables in a single payload and work with data. As usual, it is + * generally important to include an incrementing value like millis() in the payloads to prevent errors. + */ + +/** + * @example Transfer.ino + * For Arduino
+ * This example demonstrates half-rate transfer using the FIFO buffers
+ * + * It is an example of how to use the RF24 class. Write this sketch to two + * different nodes. Put one of the nodes into 'transmit' mode by connecting
+ * with the serial monitor and sending a 'T'. The data transfer will begin, + * with the receiver displaying the payload count. (32Byte Payloads)
+ */ + + /** + * @example transfer.cpp + * For Linux
+ * This example demonstrates half-rate transfer using the FIFO buffers
+ * + * It is an example of how to use the RF24 class. Write this sketch to two + * different nodes. Put one of the nodes into 'transmit' mode by connecting
+ * with the serial monitor and sending a 'T'. The data transfer will begin, + * with the receiver displaying the payload count. (32Byte Payloads)
+ */ + +/** + * @example TransferTimeouts.ino + * New: TMRh20
+ * This example demonstrates the use of and extended timeout period and + * auto-retries/auto-reUse to increase reliability in noisy or low signal scenarios.
+ * + * Write this sketch to two different nodes. Put one of the nodes into 'transmit' + * mode by connecting with the serial monitor and sending a 'T'. The data
+ * transfer will begin, with the receiver displaying the payload count and the + * data transfer rate. + */ + +/** + * @example starping.pde + * + * This sketch is a more complex example of using the RF24 library for Arduino. + * Deploy this on up to six nodes. Set one as the 'pong receiver' by tying the + * role_pin low, and the others will be 'ping transmit' units. The ping units + * unit will send out the value of millis() once a second. The pong unit will + * respond back with a copy of the value. Each ping unit can get that response + * back, and determine how long the whole cycle took. + * + * This example requires a bit more complexity to determine which unit is which. + * The pong receiver is identified by having its role_pin tied to ground. + * The ping senders are further differentiated by a byte in eeprom. + */ + +/** + * @example pingpair_ack.ino + * Update: TMRh20
+ * This example continues to make use of all the normal functionality of the radios including + * the auto-ack and auto-retry features, but allows ack-payloads to be written optionlly as well.
+ * This allows very fast call-response communication, with the responding radio never having to + * switch out of Primary Receiver mode to send back a payload, but having the option to if wanting
+ * to initiate communication instead of respond to a commmunication. + */ + +/** + * @example pingpair_irq.ino + * Update: TMRh20
+ * This is an example of how to user interrupts to interact with the radio, and a demonstration + * of how to use them to sleep when receiving, and not miss any payloads.
+ * The pingpair_sleepy example expands on sleep functionality with a timed sleep option for the transmitter. + * Sleep functionality is built directly into my fork of the RF24Network library
+ */ + + /** + * @example pingpair_irq_simple.ino + * Dec 2014 - TMRh20
+ * This is an example of how to user interrupts to interact with the radio, with bidirectional communication. + */ + +/** + * @example pingpair_sleepy.ino + * Update: TMRh20
+ * This is an example of how to use the RF24 class to create a battery- + * efficient system. It is just like the GettingStarted_CallResponse example, but the
+ * ping node powers down the radio and sleeps the MCU after every + * ping/pong cycle, and the receiver sleeps between payloads.
+ */ + + /** + * @example rf24ping85.ino + * New: Contributed by https://github.com/tong67
+ * This is an example of how to use the RF24 class to communicate with ATtiny85 and other node.
+ */ + + /** + * @example timingSearch3pin.ino + * New: Contributed by https://github.com/tong67
+ * This is an example of how to determine the correct timing for ATtiny when using only 3-pins + */ + +/** + * @example pingpair_dyn.ino + * + * This is an example of how to use payloads of a varying (dynamic) size on Arduino. + */ + + /** + * @example pingpair_dyn.cpp + * + * This is an example of how to use payloads of a varying (dynamic) size on Linux. + */ + +/** + * @example pingpair_dyn.py + * + * This is a python example for RPi of how to use payloads of a varying (dynamic) size. + */ + +/** + * @example scanner.ino + * + * Example to detect interference on the various channels available. + * This is a good diagnostic tool to check whether you're picking a + * good channel for your application. + * + * Inspired by cpixip. + * See http://arduino.cc/forum/index.php/topic,54795.0.html + */ + +/** + * @mainpage Optimized High Speed Driver for nRF24L01(+) 2.4GHz Wireless Transceiver + * + * @section Goals Design Goals + * + * This library fork is designed to be... + * @li More compliant with the manufacturer specified operation of the chip, while allowing advanced users + * to work outside the recommended operation. + * @li Utilize the capabilities of the radio to their full potential via Arduino + * @li More reliable, responsive, bug-free and feature rich + * @li Easy for beginners to use, with well documented examples and features + * @li Consumed with a public interface that's similar to other Arduino standard libraries + * + * @section News News + * + * **Dec 2015**
+ * - ESP8266 support via Arduino IDE + * - Particle Photon/Core fork available + * - ATTiny2313/4313 support added + * - Python 3 support added + * - RF24 added to Arduino library manager + * - RF24 added to PlatformIO library manager + * + * **March 2015**
+ * - Uses SPI transactions on Arduino + * - New layout for easier portability: Break out defines & includes for individual platforms to RF24/utility + * - MRAA support added ( Galileo, Edison, etc) + * - Generic Linux support (SPIDEV) support + * - Support for RPi 2 added + * - Major Documentation cleanup & update (Move all docs to github.io) + * + * + * If issues are discovered with the documentation, please report them here + * + *
+ * @section Useful Useful References + * + * + * @li RF24 Class Documentation + * @li Download + * @li Source Code + * @li My Blog: RF24 Optimization Overview + * @li My Blog: RPi/Linux w/RF24Gateway + * @li Chip Datasheet + * + * **Additional Information and Add-ons** + * + * @li RF24Network: OSI Network Layer for multi-device communication. Create a home sensor network. + * @li RF24Mesh: Dynamic Mesh Layer for RF24Network + * @li RF24Ethernet: TCP/IP Radio Mesh Networking (shares Arduino Ethernet API) + * @li RF24Audio: Realtime Wireless Audio streaming + * @li All TMRh20 Documentation Main Page + * + * **More Information and RF24 Based Projects** + * + * @li Project Blog: TMRh20.blogspot.com + * @li Maniacal Bits Blog + * @li MySensors.org (User friendly sensor networks/IoT) + * @li RF24Node_MsgProto (MQTT) + * @li RF24SensorNet + * @li Home Automation for Geeks + * @li Original Maniacbug RF24Network Blog Post + * @li ManiacBug on GitHub (Original Library Author) + * + * + *
+ * + * @section Platform_Support Platform Support Pages + * + * @li Arduino (Uno, Nano, Mega, Due, Galileo, etc) + * @li ATTiny + * @li Linux devices( RPi , Linux SPI userspace device, MRAA supported boards ( Galileo, Edison, etc), LittleWire) + * @li Cross-compilation for linux devices + * @li Python wrapper available for Linux devices + * + *
+ * **General µC Pin layout** (See the individual board support pages for more info) + * + * The table below shows how to connect the the pins of the NRF24L01(+) to different boards. + * CE and CSN are configurable. + * + * | PIN | NRF24L01 | Arduino UNO | ATtiny25/45/85 [0] | ATtiny44/84 [1] | LittleWire [2] | RPI | RPi -P1 Connector | + * |-----|----------|-------------|--------------------|-----------------|-------------------------|------------|-------------------| + * | 1 | GND | GND | pin 4 | pin 14 | GND | rpi-gnd | (25) | + * | 2 | VCC | 3.3V | pin 8 | pin 1 | regulator 3.3V required | rpi-3v3 | (17) | + * | 3 | CE | digIO 7 | pin 2 | pin 12 | pin to 3.3V | rpi-gpio22 | (15) | + * | 4 | CSN | digIO 8 | pin 3 | pin 11 | RESET | rpi-gpio8 | (24) | + * | 5 | SCK | digIO 13 | pin 7 | pin 9 | SCK | rpi-sckl | (23) | + * | 6 | MOSI | digIO 11 | pin 6 | pin 7 | MOSI | rpi-mosi | (19) | + * | 7 | MISO | digIO 12 | pin 5 | pin 8 | MISO | rpi-miso | (21) | + * | 8 | IRQ | - | - | - | - | - | - | + * + * @li [0] https://learn.sparkfun.com/tutorials/tiny-avr-programmer-hookup-guide/attiny85-use-hints + * @li [1] http://highlowtech.org/?p=1695 + * @li [2] http://littlewire.cc/ + *


+ * + * + * + * + * @page Arduino Arduino + * + * RF24 is fully compatible with Arduino boards
+ * See http://www.arduino.cc/en/Reference/Board and http://arduino.cc/en/Reference/SPI for more information + * + * RF24 makes use of the standard hardware SPI pins (MISO,MOSI,SCK) and requires two additional pins, to control + * the chip-select and chip-enable functions.
+ * These pins must be chosen and designated by the user, in RF24 radio(ce_pin,cs_pin); and can use any + * available pins. + * + *
+ * @section ARD_DUE Arduino Due + * + * RF24 makes use of the extended SPI functionality available on the Arduino Due, and requires one of the + * defined hardware SS/CS pins to be designated in RF24 radio(ce_pin,cs_pin);
+ * See http://arduino.cc/en/Reference/DueExtendedSPI for more information + * + * Initial Due support taken from https://github.com/mcrosson/RF24/tree/due + * + *
+ * @section Alternate_SPI Alternate SPI Support + * + * RF24 supports alternate SPI methods, in case the standard hardware SPI pins are otherwise unavailable. + * + *
+ * **Software Driven SPI** + * + * Software driven SPI is provided by the DigitalIO library + * + * Setup:
+ * 1. Install the digitalIO library
+ * 2. Open RF24_config.h in a text editor. + Uncomment the line + @code + #define SOFTSPI + @endcode + or add the build flag/option + @code + -DSOFTSPI + @endcode + * 3. In your sketch, add + * @code + * #include DigitalIO.h + * @endcode + * + * @note Note: Pins are listed as follows and can be modified by editing the RF24_config.h file
+ * + * #define SOFT_SPI_MISO_PIN 16 + * #define SOFT_SPI_MOSI_PIN 15 + * #define SOFT_SPI_SCK_PIN 14 + * Or add the build flag/option + * + * -DSOFT_SPI_MISO_PIN=16 -DSOFT_SPI_MOSI_PIN=15 -DSOFT_SPI_SCK_PIN=14 + * + *
+ * **Alternate Hardware (UART) Driven SPI** + * + * The Serial Port (UART) on Arduino can also function in SPI mode, and can double-buffer data, while the + * default SPI hardware cannot. + * + * The SPI_UART library is available at https://github.com/TMRh20/Sketches/tree/master/SPI_UART + * + * Enabling: + * 1. Install the SPI_UART library + * 2. Edit RF24_config.h and uncomment #define SPI_UART + * 3. In your sketch, add @code #include @endcode + * + * SPI_UART SPI Pin Connections: + * | NRF |Arduino Uno Pin| + * |-----|---------------| + * | MOSI| TX(0) | + * | MISO| RX(1) | + * | SCK | XCK(4) | + * | CE | User Specified| + * | CSN | User Specified| + * + * + * @note SPI_UART on Mega boards requires soldering to an unused pin on the chip.
See + * https://github.com/TMRh20/RF24/issues/24 for more information on SPI_UART. + * + * @page ATTiny ATTiny + * + * ATTiny support is built into the library, so users are not required to include SPI.h in their sketches
+ * See the included rf24ping85 example for pin info and usage + * + * Some versions of Arduino IDE may require a patch to allow use of the full program space on ATTiny
+ * See https://github.com/TCWORLD/ATTinyCore/tree/master/PCREL%20Patch%20for%20GCC for ATTiny patch + * + * ATTiny board support initially added from https://github.com/jscrane/RF24 + * + * @section Hardware Hardware Configuration + * By tong67 ( https://github.com/tong67 ) + * + * **ATtiny25/45/85 Pin map with CE_PIN 3 and CSN_PIN 4** + * @code + * +-\/-+ + * NC PB5 1|o |8 Vcc --- nRF24L01 VCC, pin2 --- LED --- 5V + * nRF24L01 CE, pin3 --- PB3 2| |7 PB2 --- nRF24L01 SCK, pin5 + * nRF24L01 CSN, pin4 --- PB4 3| |6 PB1 --- nRF24L01 MOSI, pin6 + * nRF24L01 GND, pin1 --- GND 4| |5 PB0 --- nRF24L01 MISO, pin7 + * +----+ + * @endcode + * + *
+ * **ATtiny25/45/85 Pin map with CE_PIN 3 and CSN_PIN 3** => PB3 and PB4 are free to use for application
+ * Circuit idea from http://nerdralph.blogspot.ca/2014/01/nrf24l01-control-with-3-attiny85-pins.html
+ * Original RC combination was 1K/100nF. 22K/10nF combination worked better.
+ * For best settletime delay value in RF24::csn() the timingSearch3pin.ino sketch can be used.
+ * This configuration is enabled when CE_PIN and CSN_PIN are equal, e.g. both 3
+ * Because CE is always high the power consumption is higher than for 5 pins solution
+ * @code + * ^^ + * +-\/-+ nRF24L01 CE, pin3 ------| // + * PB5 1|o |8 Vcc --- nRF24L01 VCC, pin2 ------x----------x--|<|-- 5V + * NC PB3 2| |7 PB2 --- nRF24L01 SCK, pin5 --|<|---x-[22k]--| LED + * NC PB4 3| |6 PB1 --- nRF24L01 MOSI, pin6 1n4148 | + * nRF24L01 GND, pin1 -x- GND 4| |5 PB0 --- nRF24L01 MISO, pin7 | + * | +----+ | + * |-----------------------------------------------||----x-- nRF24L01 CSN, pin4 + * 10nF + * @endcode + * + *
+ * **ATtiny24/44/84 Pin map with CE_PIN 8 and CSN_PIN 7**
+ * Schematic provided and successfully tested by Carmine Pastore (https://github.com/Carminepz)
+ * @code + * +-\/-+ + * nRF24L01 VCC, pin2 --- VCC 1|o |14 GND --- nRF24L01 GND, pin1 + * PB0 2| |13 AREF + * PB1 3| |12 PA1 + * PB3 4| |11 PA2 --- nRF24L01 CE, pin3 + * PB2 5| |10 PA3 --- nRF24L01 CSN, pin4 + * PA7 6| |9 PA4 --- nRF24L01 SCK, pin5 + * nRF24L01 MISO, pin7 --- PA6 7| |8 PA5 --- nRF24L01 MOSI, pin6 + * +----+ + * @endcode + * + *
+ * **ATtiny2313/4313 Pin map with CE_PIN 12 and CSN_PIN 13**
+ * @code + * +-\/-+ + * PA2 1|o |20 VCC --- nRF24L01 VCC, pin2 + * PD0 2| |19 PB7 --- nRF24L01 SCK, pin5 + * PD1 3| |18 PB6 --- nRF24L01 MOSI, pin6 + * PA1 4| |17 PB5 --- nRF24L01 MISO, pin7 + * PA0 5| |16 PB4 --- nRF24L01 CSN, pin4 + * PD2 6| |15 PB3 --- nRF24L01 CE, pin3 + * PD3 7| |14 PB2 + * PD4 8| |13 PB1 + * PD5 9| |12 PB0 + * nRF24L01 GND, pin1 --- GND 10| |11 PD6 + * +----+ + * @endcode + * + *


+ * + * + * + * + * + * + * @page Linux Linux devices + * + * Generic Linux devices are supported via SPIDEV, MRAA, RPi native via BCM2835, or using LittleWire. + * + * @note The SPIDEV option should work with most Linux systems supporting spi userspace device.
+ * + *
+ * @section AutoInstall Automated Install + *(**Designed & Tested on RPi** - Defaults to SPIDEV on devices supporting it) + * + * + * 1. Install prerequisites if there are any (MRAA, LittleWire libraries, setup SPI device etc) + * 2. Download the install.sh file from http://tmrh20.github.io/RF24Installer/RPi/install.sh + * @code wget http://tmrh20.github.io/RF24Installer/RPi/install.sh @endcode + * 3. Make it executable + * @code chmod +x install.sh @endcode + * 4. Run it and choose your options + * @code ./install.sh @endcode + * 5. Run an example from one of the libraries + * @code + * cd rf24libs/RF24/examples_linux + * @endcode + * Edit the gettingstarted example, to set your pin configuration + * @code nano gettingstarted.cpp + * make + * sudo ./gettingstarted + * @endcode + * + *
+ * @section ManInstall Manual Install + * 1. Install prerequisites if there are any (MRAA, LittleWire libraries, setup SPI device etc) + * @note See the MRAA documentation for more info on installing MRAA
+ * 2. Make a directory to contain the RF24 and possibly RF24Network lib and enter it + * @code + * mkdir ~/rf24libs + * cd ~/rf24libs +* @endcode + * 3. Clone the RF24 repo + * @code git clone https://github.com/tmrh20/RF24.git RF24 @endcode + * 4. Change to the new RF24 directory + * @code cd RF24 @endcode + * 5. Configure build environment using @code ./configure @endcode script. It auto detectes device and build environment. For overriding autodetections, use command-line switches, see @code ./configure --help @endcode for description. + * 6. Build the library, and run an example file + * @code sudo make install @endcode + * @code + * cd examples_linux + * @endcode + * Edit the gettingstarted example, to set your pin configuration + * @code nano gettingstarted.cpp + * make + * sudo ./gettingstarted + * @endcode + * + *

+ * + * @page MRAA MRAA + * + * MRAA is a Low Level Skeleton Library for Communication on GNU/Linux platforms
+ * See http://iotdk.intel.com/docs/master/mraa/index.html for more information + * + * RF24 supports all MRAA supported platforms, but might not be tested on each individual platform due to the wide range of hardware support:
+ * Report an RF24 bug or issue + * + * @section Setup Setup and installation + * 1. Install the MRAA lib + * 2. As per your device, SPI may need to be enabled + * 3. Follow Linux installation steps to install RF24 libraries + * + * + *


+ * + * + * + * + * @page RPi Raspberry Pi + * + * RF24 supports a variety of Linux based devices via various drivers. Some boards like RPi can utilize multiple methods + * to drive the GPIO and SPI functionality. + * + *
+ * @section PreConfig Potential PreConfiguration + * + * If SPI is not already enabled, load it on boot: + * @code sudo raspi-config @endcode + * A. Update the tool via the menu as required
+ * B. Select **Advanced** and **enable the SPI kernel module**
+ * C. Update other software and libraries + * @code sudo apt-get update @endcode + * @code sudo apt-get upgrade @endcode + *

+ * + * @section Build Build Options + * The default build on Raspberry Pi utilizes the included **BCM2835** driver from http://www.airspayce.com/mikem/bcm2835 + * 1. @code sudo make install -B @endcode + * + * Build using the **MRAA** library from http://iotdk.intel.com/docs/master/mraa/index.html
+ * MRAA is not included. See the MRAA platform page for more information. + * + * 1. Install, and build MRAA + * @code + * git clone https://github.com/intel-iot-devkit/mraa.git + * cd mraa + * mkdir build + * cd build + * cmake .. -DBUILDSWIGNODE=OFF + * sudo make install + * @endcode + * + * 2. Complete the install
+ * @code nano /etc/ld.so.conf @endcode + * Add the line @code /usr/local/lib/arm-linux-gnueabihf @endcode + * Run @code sudo ldconfig @endcode + * + * 3. Install RF24, using MRAA + * @code + * ./configure --driver=MRAA + * sudo make install -B + * @endcode + * See the gettingstarted example for an example of pin configuration + * + * Build using **SPIDEV** + * + * 1. Make sure that spi device support is enabled and /dev/spidev\.\ is present + * 2. Install RF24, using SPIDEV + * @code + * ./configure --driver=SPIDEV + * sudo make install -B + * @endcode + * 3. See the gettingstarted example for an example of pin configuration + * + *
+ * @section Pins Connections and Pin Configuration + * + * + * Using pin 15/GPIO 22 for CE, pin 24/GPIO8 (CE0) for CSN + * + * Can use either RPi CE0 or CE1 pins for radio CSN.
+ * Choose any RPi output pin for radio CE pin. + * + * **BCM2835 Constructor:** + * @code + * RF24 radio(RPI_V2_GPIO_P1_15,BCM2835_SPI_CS0, BCM2835_SPI_SPEED_8MHZ); + * or + * RF24 radio(RPI_V2_GPIO_P1_15,BCM2835_SPI_CS1, BCM2835_SPI_SPEED_8MHZ); + * + * RPi B+: + * RF24 radio(RPI_BPLUS_GPIO_J8_15,RPI_BPLUS_GPIO_J8_24, BCM2835_SPI_SPEED_8MHZ); + * or + * RF24 radio(RPI_BPLUS_GPIO_J8_15,RPI_BPLUS_GPIO_J8_26, BCM2835_SPI_SPEED_8MHZ); + * + * General: + * RF24 radio(22,0); + * or + * RF24 radio(22,1); + * + * @endcode + * See the gettingstarted example for an example of pin configuration + * + * See http://www.airspayce.com/mikem/bcm2835/index.html for BCM2835 class documentation. + *

+ * **MRAA Constructor:** + * + * @code RF24 radio(15,0); @endcode + * + * See http://iotdk.intel.com/docs/master/mraa/rasppi.html + *

+ * **SPI_DEV Constructor** + * + * @code RF24 radio(22,0); @endcode + * In general, use @code RF24 radio(, *10+); @endcode for proper SPIDEV constructor to address correct spi device at /dev/spidev\.\ + * + * See http://pi.gadgetoid.com/pinout + * + * **Pins:** + * + * | PIN | NRF24L01 | RPI | RPi -P1 Connector | + * |-----|----------|------------|-------------------| + * | 1 | GND | rpi-gnd | (25) | + * | 2 | VCC | rpi-3v3 | (17) | + * | 3 | CE | rpi-gpio22 | (15) | + * | 4 | CSN | rpi-gpio8 | (24) | + * | 5 | SCK | rpi-sckl | (23) | + * | 6 | MOSI | rpi-mosi | (19) | + * | 7 | MISO | rpi-miso | (21) | + * | 8 | IRQ | - | - | + * + * + * + * + *

+ **************** + * + * Based on the arduino lib from J. Coliz
+ * the library was berryfied by Purinda Gunasekara
+ * then forked from github stanleyseow/RF24 to https://github.com/jscrane/RF24-rpi
+ * Network lib also based on https://github.com/farconada/RF24Network + * + * + * + * + *


+ * + * + * + * @page Python Python Wrapper (by https://github.com/mz-fuzzy) + * + * @note Both python2 and python3 are supported. + * + * @section Install Installation: + * + * 1. Install the python-dev (or python3-dev) and boost libraries + * @code sudo apt-get install python-dev libboost-python-dev @endcode + * @note For python3 in Raspbian, it's needed to manually link python boost library, like this: + * @code sudo ln -s /usr/lib/arm-linux-gnueabihf/libboost_python-py34.so /usr/lib/arm-linux-gnueabihf/libboost_python3.so @endcode + * + * 2. Install python-setuptools (or python3-setuptools) + * @code sudo apt-get install python-setuptools @endcode + * + * 3. Build the library + * @code ./setup.py build @endcode + * @note Build takes several minutes on arm-based machines. Machines with RAM <1GB may need to increase amount of swap for build. + * + * 4. Install the library + * @code sudo ./setup.py install @endcode + * See the additional
Platform Support pages for information on connecting your hardware
+ * See the included example for usage information. + * + * 5. Running the Example + * Edit the pingpair_dyn.py example to configure the appropriate pins per the above documentation: + * @code nano pingpair_dyn.py @endcode + * Configure another device, Arduino or RPi with the pingpair_dyn example
+ * Run the example + * @code sudo ./pingpair_dyn.py @endcode + * + *


+ * + * @page CrossCompile Linux cross-compilation + * + * RF24 library supports cross-compilation. Advantages of cross-compilation: + * - development tools don't have to be installed on target machine + * - resources of target machine don't have to be sufficient for compilation + * - compilation time can be reduced for large projects + * + * Following prerequisites need to be assured: + * - ssh passwordless access to target machine (https://linuxconfig.org/passwordless-ssh) + * - sudo of a remote user without password (http://askubuntu.com/questions/334318/sudoers-file-enable-nopasswd-for-user-all-commands) + * - cross-compilation toolchain for your target machine; for RPi + * @code git clone https://github.com/raspberrypi/tools rpi_tools @endcode + * and cross-compilation tools must be in PATH, for example + * @code export PATH=$PATH:/your/dir/rpi-tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin @endcode + * + * @section CxSteps Cross compilation steps: + * 1. clone RF24 to a machine for cross-compilation + * @code + * git clone https://github.com/TMRh20/RF24 + * cd RF24 + * @endcode + * 2. configure for cross compilation + * @code ./configure --remote=pi@target_linux_host @endcode + * eventually + * @code ./configure --remote=pi@target_linux_host --driver= @endcode + * 3. build + * @code make @endcode + * 4. (opt) install library to cross-compilation machine into cross-exvironment - important for compilation of examples + * @code sudo make install @endcode + * 5. upload library to target machine + * @code make upload @endcode + * 6. (opt) compile examples + * @code + * cd examples_linux + * make + * @endcode + * 7. (opt) upload examples to target machine + * @code make upload @endcode + * + * @section CxStepsPython Cross comilation steps for python wrapper + * + * Prerequisites: + * - Python setuptools must be installed on both target and cross-compilation machines + * @code sudo pip install setuptools @endcode + * or + * @code sudo apt-get install python-setuptools @endcode + * + * Installation steps: + * 1. Assure having libboost-python-dev library in your cross-compilation environment. Alternatively, you can install it into your target machine and copy /usr and /lib directories to the cross-compilation machine. + * For example + * @code + * mkdir -p rpi_root && rsync -a pi@target_linux_host:/usr :/lib rpi_root + * export CFLAGS="--sysroot=/your/dir/rpi_root -I/your/dir/rpi_root/usr/include/python2.7/" + * @endcode + * + * 2. Build the python wrapper + * @code + * cd pyRF24 + * ./setup.py build --compiler=crossunix + * @endcode + * + * 3. Make the egg package + * @code ./setup.py bdist_egg --plat-name=cross @endcode + * dist/RF24--cross.egg should be created. + * + * 4. Upload it to the target machine and install there: + * @code + * scp dist/RF24-*-cross.egg pi@target_linux_host: + * ssh pi@target_linux_host 'sudo easy_install RF24-*-cross.egg' + * @endcode + * + *


+ * + * @page ATXMEGA ATXMEGA + * + * The RF24 driver can be build as a static library with Atmel Studio 7 in order to be included as any other library in another program for the XMEGA family. + * + * Currently only the ATXMEGA D3 family is implemented. + * + * @section Preparation + * + * Create an empty GCC Static Library project in AS7.
+ * As not all files are required, copy the following directory structure in the project: + * + * @code + * utility\ + * ATXMegaD3\ + * compatibility.c + * compatibility.h + * gpio.cpp + * gpio.h + * gpio_helper.c + * gpio_helper.h + * includes.h + * RF24_arch_config.h + * spi.cpp + * spi.h + * nRF24L01.h + * printf.h + * RF24.cpp + * RF24.h + * RF24_config.h + * @endcode + * + * @section Usage + * + * Add the library to your project!
+ * In the file where the **main()** is put the following in order to update the millisecond functionality: + * + * @code + * ISR(TCE0_OVF_vect) + * { + * update_milisec(); + * } + * @endcode + * + * Declare the rf24 radio with **RF24 radio(XMEGA_PORTC_PIN3, XMEGA_SPI_PORT_C);** + * + * First parameter is the CE pin which can be any available pin on the uC. + * + * Second parameter is the CS which can be on port C (**XMEGA_SPI_PORT_C**) or on port D (**XMEGA_SPI_PORT_D**). + * + * Call the **__start_timer()** to start the millisecond timer. + * + * @note Note about the millisecond functionality:
+ * + * The millisecond functionality is based on the TCE0 so don't use these pins as IO.
+ * The operating frequency of the uC is 32MHz. If you have other frequency change the TCE0 registers appropriatly in function **__start_timer()** in **compatibility.c** file for your frequency. + * + * @page Portability RF24 Portability + * + * The RF24 radio driver mainly utilizes the Arduino API for GPIO, SPI, and timing functions, which are easily replicated + * on various platforms.
Support files for these platforms are stored under RF24/utility, and can be modified to provide + * the required functionality. + * + *
+ * @section Hardware_Templates Basic Hardware Template + * + * **RF24/utility** + * + * The RF24 library now includes a basic hardware template to assist in porting to various platforms.
The following files can be included + * to replicate standard Arduino functions as needed, allowing devices from ATTiny to Raspberry Pi to utilize the same core RF24 driver. + * + * | File | Purpose | + * |--------------------|------------------------------------------------------------------------------| + * | RF24_arch_config.h | Basic Arduino/AVR compatibility, includes for remaining support files, etc | + * | includes.h | Linux only. Defines specific platform, include correct RF24_arch_config file | + * | spi.h | Provides standardized SPI ( transfer() ) methods | + * | gpio.h | Provides standardized GPIO ( digitalWrite() ) methods | + * | compatibility.h | Provides standardized timing (millis(), delay()) methods | + * | your_custom_file.h | Provides access to custom drivers for spi,gpio, etc | + * + *
+ * Examples are provided via the included hardware support templates in **RF24/utility**
+ * See the modules page for examples of class declarations + * + *
+ * @section Device_Detection Device Detection + * + * 1. The main detection for Linux devices is done in the configure script, with the includes.h from the proper hardware directory copied to RF24/utility/includes.h
+ * 2. Secondary detection is completed in RF24_config.h, causing the include.h file to be included for all supported Linux devices
+ * 3. RF24.h contains the declaration for SPI and GPIO objects 'spi' and 'gpio' to be used for porting-in related functions. + * + *
+ * @section Ported_Code Code + * To have your ported code included in this library, or for assistance in porting, create a pull request or open an issue at https://github.com/TMRh20/RF24 + * + * + *


+ */ + +#endif // __RF24_H__ diff --git a/Software/ATmega32U4_nl/RF24_config.h b/Software/ATmega32U4_nl/RF24_config.h new file mode 100644 index 0000000..5e0c215 --- /dev/null +++ b/Software/ATmega32U4_nl/RF24_config.h @@ -0,0 +1,163 @@ + +/* + Copyright (C) 2011 J. Coliz + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + */ + + /* spaniakos + Added __ARDUINO_X86__ support +*/ + +#ifndef __RF24_CONFIG_H__ +#define __RF24_CONFIG_H__ + + /*** USER DEFINES: ***/ + //#define FAILURE_HANDLING + //#define SERIAL_DEBUG + //#define MINIMAL + //#define SPI_UART // Requires library from https://github.com/TMRh20/Sketches/tree/master/SPI_UART + //#define SOFTSPI // Requires library from https://github.com/greiman/DigitalIO + + /**********************/ + #define rf24_max(a,b) (a>b?a:b) + #define rf24_min(a,b) (a + + // RF modules support 10 Mhz SPI bus speed + const uint32_t RF24_SPI_SPEED = 10000000; + +#if defined (ARDUINO) && !defined (__arm__) && !defined (__ARDUINO_X86__) + #if defined SPI_UART + #include + #define _SPI uspi + #elif defined SOFTSPI + // change these pins to your liking + // + #ifndef SOFT_SPI_MISO_PIN + #define SOFT_SPI_MISO_PIN 9 + #endif + + #ifndef SOFT_SPI_MOSI_PIN + #define SOFT_SPI_MOSI_PIN 8 + #endif + + #ifndef SOFT_SPI_SCK_PIN + #define SOFT_SPI_SCK_PIN 7 + #endif + const uint8_t SPI_MODE = 0; + #define _SPI spi + + #else + #include + #define _SPI SPI + #endif +#else + // Define _BV for non-Arduino platforms and for Arduino DUE + #include + #include + #include + + + #if defined(__arm__) || defined (__ARDUINO_X86__) + #if defined (__arm__) && defined (SPI_UART) + #include + #define _SPI uspi + #else + #include + #define _SPI SPI + #endif + #elif !defined(__arm__) && !defined (__ARDUINO_X86__) + extern HardwareSPI SPI; + #endif + + #define _BV(x) (1<<(x)) + +#endif + + #ifdef SERIAL_DEBUG + #define IF_SERIAL_DEBUG(x) ({x;}) + #else + #define IF_SERIAL_DEBUG(x) + #if defined(RF24_TINY) + #define printf_P(...) + #endif + #endif + +#if defined (__ARDUINO_X86__) + #define printf_P printf + #define _BV(bit) (1<<(bit)) +#endif + +// Progmem is Arduino-specific +// Arduino DUE is arm and does not include avr/pgmspace +#if defined (ARDUINO_ARCH_ESP8266) + + #include + #define PRIPSTR "%s" + +#elif defined(ARDUINO) && !defined(ESP_PLATFORM) && ! defined(__arm__) && !defined (__ARDUINO_X86__) || defined(XMEGA) + #include + #define PRIPSTR "%S" +#else + #if ! defined(ARDUINO) // This doesn't work on Arduino DUE + typedef char const char; + #else // Fill in pgm_read_byte that is used, but missing from DUE + #define pgm_read_byte(addr) (*(const unsigned char *)(addr)) + #endif + + + typedef uint16_t prog_uint16_t; + #define PSTR(x) (x) + #define printf_P printf + #define strlen_P strlen + #define PROGMEM + #define pgm_read_word(p) (*(p)) + + #define PRIPSTR "%s" + +#endif + +#endif + + + +#endif // __RF24_CONFIG_H__ diff --git a/Software/ATmega32U4_nl/SerialCommunication.h b/Software/ATmega32U4_nl/SerialCommunication.h new file mode 100644 index 0000000..4b29099 --- /dev/null +++ b/Software/ATmega32U4_nl/SerialCommunication.h @@ -0,0 +1,131 @@ +/* +Communiceer met de ESP8266 via de seriële poort om de gegevens naar de webachtergrond weer te geven. +De achtergrondtransmissie en aanvalshandelingen worden via de seriële poort naar de 32U4 verzonden voor uitvoering. +   32U4 -> esp8266 voert gesnuffelde gegevens terug naar de webachtergrond +   Vaste code / rolling code gegevens gesnoven door CC1101 / nRF24L01 + [RF][Sniffer]freq:315,protocol:Fixed-1,modulation:ask,func:1,data:B710 + [RF][Sniffer]freq:433,protocol:keeloq,modulation:ask,data:a9df5d4c,SerialNumber:39182da + [RF][Sniffer]freq:2.4G,protocol:rf24l01,modulation:gfsk,data:401FFFFFF02AE9 + [RF][Sniffer]freq:433,protocol:keeloq,modulation: ask,data:2d6f28d4,SerialNumber:39182da + CC1101 Signaaldetectiegegevens in intelligente interferentiemodus + [RF][Jam]-9b 433Mhz/Jamming.../[RF][Jam]Not Jamming + EM4095 Lees kaartnummerinformatie + [NFC][read]vd:123,data:1432455555 + Voortgang in de aanvalsmodus + [NFC][progress]100 + [RF][Progress]100 + + + 32U4 <- esp8266 Verzend instructies via de webinterface + Verzend een vast codesignaal via CC1101 + [RF][Transmit]315,1,B710 + Lancering van een lichtbalksignaal via CC1101 + [RF][Transmit]LigthBar,freq:315,data:2600 + Vaste code stralen + [RF][Attack]Class2,freq:315,start:B701,end:B710,func:1 + FSK modulatie bandenspanningssignaal verzonden door CC1101 + [RF][TPMS]2093ef85A0203300 + Interferentie door CC1101 + [RF][Jam]class:Smart,freq1:433920000,freq2:315000000 + [RF][Jam]class:Rude,freq:433920000 + [RF][Jam]Stop + Schakel CC1101, nRF24l01 voeding uit / in + [RF][Switch]action:off/on + //Stel de RF-chipinformatie in + [RF][Setup]chip:CC1101,class:fixed,freq:315000000 + [RF][Setup]chip:CC1101,class:keeloq,freq:433920000 + [RF][Setup]chip:nRF24L01,class:keeloq,freq:315000000 + Analoge laagfrequente kaartfunctie + [NFC][simulation]vd:123,data:4294967295 + [NFC][attack]vd:123,start:4294967205,end:4294967295 + Schakel de EM4095-voeding in, werkende laagfrequentiechip + [NFC][switch]action:off/on + Laagfrequente kaartschrijffunctie + [NFC][write]vd:22,data:33333 + Badusb functie + [HID]test +*/ + +void SerialCommunication() { + while (Cube_PRINT.available() > 0) { + Cube_PRINT_data += char(Cube_PRINT.read()); + delay(4); + } + if (Cube_PRINT_data.length() > 0) { + if (Cube_PRINT_data.substring(1, 4) == "HID") { //h + hid_attack(); + } else if (Cube_PRINT_data.substring(1, 3) == "RF") { + + if (int(Cube_PRINT_data.indexOf("Jam")) > 0) { + String Jam_Class = Cube_PRINT_data.substring(Cube_PRINT_data.indexOf("class") + 6, Cube_PRINT_data.indexOf(",freq")); + if (Jam_Class == "Smart") { + freq1 = strtoul(Cube_PRINT_data.substring(Cube_PRINT_data.indexOf("freq1") + 6, Cube_PRINT_data.indexOf(",freq2")).c_str(), NULL, 10); + freq2 = strtoul(Cube_PRINT_data.substring(Cube_PRINT_data.indexOf("freq2") + 6, Cube_PRINT_data.length()).c_str(), NULL, 10); + RF_action = 1; + + RF_Jam(); + } else if (Jam_Class == "Rude") { + freq = strtoul(Cube_PRINT_data.substring(Cube_PRINT_data.indexOf("freq") + 5, Cube_PRINT_data.length()).c_str(), NULL, 10); + //Serial.println(freq); + RF_action = 2; + RF_Jam(); + } + + } else if (int(Cube_PRINT_data.indexOf("TPMS")) > 0) { + CC1101_TPMS_TX(); + } else if (int(Cube_PRINT_data.indexOf("Transmit")) > 0) { + if (int(Cube_PRINT_data.indexOf("LigthBar")) > 0) { + RF_LigthBar(); + } else { + RF_Transmit(); + } + } else if (int(Cube_PRINT_data.indexOf("Attack")) > 0) { + RF_Attack(); + } else if (int(Cube_PRINT_data.indexOf("Switch")) > 0) { + RF_Switch(Cube_PRINT_data.substring(Cube_PRINT_data.indexOf("action") + 7, Cube_PRINT_data.indexOf('\r'))); + } else if (int(Cube_PRINT_data.indexOf("Setup")) > 0) { + if (int(Cube_PRINT_data.indexOf("CC1101")) > 0) { + cc1101_Setup(); + } else if (int(Cube_PRINT_data.indexOf("nRF24L01")) > 0) { + + } + } + } else if (Cube_PRINT_data.substring(1, 4) == "NFC") { + if (Cube_PRINT_data.substring(6, 16) == "simulation") { + NFC_action = 1; + NFC_VD = atoi(Cube_PRINT_data.substring(Cube_PRINT_data.indexOf("vd") + 3, Cube_PRINT_data.indexOf(",data")).c_str()); + NFC_ID = strtoul(Cube_PRINT_data.substring(Cube_PRINT_data.indexOf("data") + 5, Cube_PRINT_data.length()).c_str(), NULL, 10); + Cube_PRINT.print("VD:"); + Cube_PRINT.print(NFC_VD); + Cube_PRINT.print("ID:"); + Cube_PRINT.println(NFC_ID); + } else if (Cube_PRINT_data.substring(6, 12) == "attack") { + NFC_action = 2; + NFC_VD = atoi(Cube_PRINT_data.substring(Cube_PRINT_data.indexOf("vd") + 3, Cube_PRINT_data.indexOf(",start")).c_str()); + NFC_START = strtoul(Cube_PRINT_data.substring(Cube_PRINT_data.indexOf("start") + 6, Cube_PRINT_data.indexOf(",end")).c_str(), NULL, 10); + NFC_END = strtoul(Cube_PRINT_data.substring(Cube_PRINT_data.indexOf("end") + 4, Cube_PRINT_data.length()).c_str(), NULL, 10); + NFC_ID = NFC_START; + Cube_PRINT.print("VD:"); + Cube_PRINT.print(NFC_VD); + Cube_PRINT.print(";Start ID:"); + Cube_PRINT.print(NFC_START); + Cube_PRINT.print(";END ID:"); + Cube_PRINT.println(NFC_END); + } else if (Cube_PRINT_data.substring(6, 12) == "switch") { + NFC_Switch(Cube_PRINT_data.substring(Cube_PRINT_data.indexOf("action") + 7, Cube_PRINT_data.indexOf('\r'))); + } else if (int(Cube_PRINT_data.indexOf("write")) > 0) { + //NFC_action = 3; + NFC_VD = atoi(Cube_PRINT_data.substring(Cube_PRINT_data.indexOf("vd") + 3, Cube_PRINT_data.indexOf(",data")).c_str()); + NFC_ID = strtoul(Cube_PRINT_data.substring(Cube_PRINT_data.indexOf("data") + 5, Cube_PRINT_data.length()).c_str(), NULL, 10); + Cube_PRINT.print("w,VD:"); + Cube_PRINT.print(NFC_VD); + Cube_PRINT.print("ID:"); + Cube_PRINT.println(NFC_ID); + EM4095.Write_ID(NFC_VD,NFC_ID); + } + } else { + Cube_PRINT.print("error:"); + Cube_PRINT.println(Cube_PRINT_data[0], HEX); + } + Cube_PRINT_data = ""; + } +} diff --git a/Software/ATmega32U4_nl/attack.h b/Software/ATmega32U4_nl/attack.h new file mode 100644 index 0000000..98a54e3 --- /dev/null +++ b/Software/ATmega32U4_nl/attack.h @@ -0,0 +1,435 @@ +#include "HackCube.h" +#include "cc1101.h" + +//HackCube hc; +//CC1101 cc1101; + +int Transmitpin = RF433_GDO0; + +//class 2 360 +#define bit_delay_1 111 //9.09k + +byte counter; +byte b; +byte syncWord[2] = {0xFF, 0xFF}; + + +void bit1_1() { + digitalWrite(Transmitpin, HIGH); + delayMicroseconds(bit_delay_1); + //digitalWrite(pin, LOW); +} +void bit0_1() { + digitalWrite(Transmitpin, LOW); + delayMicroseconds(bit_delay_1); +} + +void Sync_1() { + // 0101 0101 0101 00 1111111111 + bit0_1(); bit1_1(); + bit0_1(); bit1_1(); + + bit0_1(); bit1_1(); + bit0_1(); bit1_1(); + + bit0_1(); bit1_1(); + bit0_1(); bit1_1(); + + bit0_1(); bit0_1(); + bit1_1(); bit1_1(); bit1_1(); bit1_1(); bit1_1(); bit1_1(); bit1_1(); bit1_1(); bit1_1(); +} + + + + + +void CC1101_TPMS() { + cc1101.SS_PIN = RF433_CS; + counter = 0; + cc1101.initTmps(); + cc1101.setSyncWord(syncWord); + //cc1101.setCarrierFreq(CFREQ_433); + //setfreqx(430000000); + setfreqx(433925000); + //setfreqx(868000000); + //setfreqx(430000000); + cc1101.disableAddressCheck(); + //cc1101.writeReg(CC1101_PATABLE, 0xc0); + + /* + const byte paTable[8] = {0x00, 0x12, 0x0e, 0x34, 0x60, 0xc5, 0xc1, 0xc0}; + cc1101.writeBurstReg(CC1101_PATABLE, (byte*)paTable, 8); + */ + + + cc1101.writeReg(CC1101_MCSM0, 0x08);// + + cc1101.writeReg(CC1101_MDMCFG2, 0x03); //fsk + cc1101.writeReg(CC1101_DEVIATN, 0x35); //fsk freq 20 + + //cc1101.writeReg(CC1101_DEVIATN, 0x24); //fsk freq 20 + + //cc1101.writeReg(CC1101_IOCFG2, 0x0d);//rssi menu + //cc1101.writeReg(CC1101_AGCCTRL2, 0xB0); + + //cc1101.writeReg(CC1101_MDMCFG4, 0xf9);// data rate + //cc1101.writeReg(CC1101_MDMCFG3, 0xFF); + + // cc1101.cmdStrobe(CC1101_STX); +} + +/* + void Transmit_360(char * data) { + String Sdata = data; + int len = Sdata.length(); + Sync_1(); + for (int i = 0; i < len; i++) { + if (String(data[i]) == "1") + bit1_1(); + else + bit0_1(); + } + } +*/ + +uint16_t crc_xmodem_update (uint16_t crc, uint8_t data) +{ + int i; + + crc = crc ^ ((uint16_t)data << 8); + for (i = 0; i < 8; i++) + { + if (crc & 0x8000) + crc = (crc << 1) ^ 0x1021; //(polynomial = 0x1021) + else + crc <<= 1; + } + return crc; +} + +uint16_t calc_crc(byte * msg, int n, uint16_t init) +{ + uint16_t x = init; + + while (n--) + { + x = crc_xmodem_update(x, (uint16_t) * msg++); + } + + return (x); +} + + + + +int lastbit; +void Transmit_bit1() { + if (lastbit) { + //Cube_PRINT.print("01"); + digitalWrite(Transmitpin, LOW); + delayMicroseconds(bit_delay_1); + digitalWrite(Transmitpin, HIGH); + delayMicroseconds(bit_delay_1); + lastbit = true; + } else { + digitalWrite(Transmitpin, HIGH); + delayMicroseconds(bit_delay_1); + digitalWrite(Transmitpin, LOW); + delayMicroseconds(bit_delay_1); + lastbit = false; + } +} +void Transmit_bit0() { + if (lastbit) { + digitalWrite(Transmitpin, LOW); + delayMicroseconds(bit_delay_1 * 2); + lastbit = false; + } else { + digitalWrite(Transmitpin, HIGH); + delayMicroseconds(bit_delay_1 * 2); + lastbit = true; + } +} + + +void Transmit_byte_1(byte data) { + for (int a = 0; a < 8; a++) { + if (data & 0x80) + Transmit_bit0(); + else + Transmit_bit1(); + data = data << 1; + } +} + + + +void Transmit_360(byte * Transmit_data) { + //int len = sizeof (Transmit_data); + int len = 8; + lastbit = true; + //Cube_PRINT.println("Tesxt"); + uint16_t crc_out = calc_crc(Transmit_data, len, 0xffff); + + //Calculate CRC on-the-fly + /*int msb = (crc_out & 0xff00) >> 8; + int lsb = (crc_out & 0x00ff) << 8; + crc_out = msb + lsb;*/ + + int msb = (crc_out & 0xff00) >> 8; + int lsb = (crc_out & 0x00ff) ; + Transmit_data[8] = lsb; + Transmit_data[9] = msb; + + len += 2; + Sync_1(); + for (int i = 0; i < len; i++) { + Transmit_byte_1(Transmit_data[i]); + //Serial.print(" "); + //Serial.print(Transmit_data[i],HEX); + } + //Serial.println(""); + + digitalWrite(Transmitpin, HIGH); + delayMicroseconds(bit_delay_1 * 3); + digitalWrite(Transmitpin, LOW); + +} + + + +void Attack_360_Car(byte * Tansmit_data) { + cc1101.cmdStrobe(CC1101_STX); + delayMicroseconds(802); + //delay(2); + //Transmit_360("0011001101010101001100110010110010101101010100110010101010110100110100110101001010101011010101001011010010101011010101010010101010101010101100110101001101001101111"); + Transmit_360(Tansmit_data); + cc1101.cmdStrobe(CC1101_SIDLE); + delay(65); + cc1101.cmdStrobe(CC1101_STX); + delayMicroseconds(802); + //Transmit_360("0011001101010101001100110010110010101101010100110010101010110100110100110101001010101011010101001011010010101011010101010010101010101010101100110101001101001101111"); + Transmit_360(Tansmit_data); + cc1101.cmdStrobe(CC1101_SIDLE); + delay(65); +} + + + +void CC1101_TPMS_TX() { + //detachInterrupt(RF315_att); + + byte TPMS_data[11]; + int a = 0; + for (int i = 10; i < Cube_PRINT_data.length(); i += 2) + { + String bdata = String(Cube_PRINT_data[i]) + String(Cube_PRINT_data[i + 1]); + + TPMS_data[a] = strtoul(bdata.c_str(), NULL, 16); + if (a == 5) + TPMS_data[a] = strtoul(bdata.c_str(), NULL, 10) * 3.2; + else if (a == 6) + TPMS_data[a] = strtoul(bdata.c_str(), NULL, 10) + 0x37; + Cube_PRINT.print(" "); + Cube_PRINT.print(TPMS_data[a], HEX); + a++; + } + //20 93 EF 85 A0 40 58 0 27 31 + //byte TPMS_data_1[11]={0x20,0x95,0x91,0x85,0xb1,0x11,0x52,0x08}; + + Cube_PRINT.println("TPMS_ok"); + Cube_PRINT_data = ""; + + CC1101_TPMS(); + delay(100); + cc1101.cmdStrobe(CC1101_SCAL); + Attack_360_Car(TPMS_data); + delay(100); + Attack_360_Car(TPMS_data); + delay(100); + // mySwitch.enableReceive(1); + cc1101_config(); + // RF315_Setup(); + // delay(4); + // Hackradio.enableReceive(RF315_att); +} + + + + +void CC1101_TPMS_TX_TEST() { + //detachInterrupt(RF315_att); + byte TPMS_data[11] = { + //20 95 91 85 A0 40 63 0 52 8C + 0x20, 0x95, 0x91, 0x85, 0xA0, 20 * 3.2, 44 + 0x37, 0x00 + }; + CC1101_TPMS(); + cc1101.PrintConfig(); + while (1) { + cc1101.cmdStrobe(CC1101_SCAL); + Attack_360_Car(TPMS_data); + delay(100); + Attack_360_Car(TPMS_data); + delay(100); + delay(1000); + } + +} + + + +/* + RF Jaming +*/ + +void Rude_Jam() { + +} + +void Smart_Jam(unsigned long freq1, unsigned long freq2, int Jam_RSSI = -73) { + + cc1101.SS_PIN = RF433_CS; + cc1101.init(); + setfreqx(433920000); + cc1101.cmdStrobe(CC1101_SRX); + //cc1101.writeReg(CC1101_IOCFG2, 0x0d); + //cc1101.writeReg(CC1101_AGCCTRL2, 0xB0); + //cc1101.PrintConfig(); + int a; + unsigned long freq; + bool Jam_flag = false, Out_flag = true; + unsigned long Jam_OutTime; + + while (1) { + + if (a) + freq = freq1; + else + freq = freq2; + a = !a; + cc1101.cmdStrobe(CC1101_SIDLE); + setfreqx(freq); + cc1101.cmdStrobe(CC1101_SRX); + delay(2); + int rssi = cc1101.readrssi(); + signed int RSSI_db; + if (rssi > 128) + RSSI_db = ((rssi - 256) / 2) - 75; + else + RSSI_db = (rssi / 2) - 75; + + if (RSSI_db > Jam_RSSI ) { + //String pinrt_data = String(freq); + //pinrt_data = pinrt_data.substring(0, 3) + "Mhz" + " Jamming..."; + cc1101.cmdStrobe(CC1101_SIDLE); + setfreqx(freq); + cc1101.cmdStrobe(CC1101_STX); + digitalWrite(RF433_GDO0, HIGH); + delay(5); + digitalWrite(RF433_GDO0, LOW); + Jam_flag = true; + Jam_OutTime = millis(); + } + if (Jam_flag && millis() - Jam_OutTime > 100) { + Cube_PRINT.println("Jam_out"); + Out_flag = true; + Jam_flag = false; + } else if (Jam_flag && Out_flag) { + Cube_PRINT.print(RSSI_db); + Cube_PRINT.print(";"); + Cube_PRINT.println(freq); + Out_flag = false; + Jam_flag = false; + } + } +} + + +int RF_action, Jam_RSSI; +unsigned long freq1, freq2, freq = 433920000; +void RF_Jam() { + + cc1101.SS_PIN = RF433_CS; + cc1101.init(); + + cc1101.cmdStrobe(CC1101_SIDLE); + setfreqx(freq); + cc1101.cmdStrobe(CC1101_STX); + digitalWrite(RF433_GDO0, HIGH); + + //cc1101.PrintConfig(); + Jam_RSSI = -73; + int a; + //unsigned long freq; + bool Jam_flag = false, Out_flag = true; + unsigned long Jam_OutTime; + + + while (RF_action) { + + switch (RF_action) { + case 1: { //Smart + if (a) + freq = freq1; + else + freq = freq2; + a = !a; + cc1101.cmdStrobe(CC1101_SIDLE); + setfreqx(freq); + cc1101.cmdStrobe(CC1101_SRX); + delay(2); + int rssi = cc1101.readrssi(); + signed int RSSI_db; + if (rssi > 128) + RSSI_db = ((rssi - 256) / 2) - 75; + else + RSSI_db = (rssi / 2) - 75; + + if (RSSI_db > Jam_RSSI ) { + //String pinrt_data = String(freq); + //pinrt_data = pinrt_data.substring(0, 3) + "Mhz" + " Jamming..."; + cc1101.cmdStrobe(CC1101_SIDLE); + setfreqx(freq); + cc1101.cmdStrobe(CC1101_STX); + digitalWrite(RF433_GDO0, HIGH); + delay(5); + digitalWrite(RF433_GDO0, LOW); + Jam_flag = true; + Jam_OutTime = millis(); + //2018年12月26日17:03:23 + if (millis() - SerialLastTime < Print_Time-200) { + //return; + } else { + String Jam_DATA = "[RF][Jam]RSSI:" + String(RSSI_db) + "dB,FREQ:" + String(freq).substring(0, 3) + "Mhz"; + Cube_PRINT.println(Jam_DATA); + SerialLastTime=Jam_OutTime=millis(); + } + } + if (Jam_flag && millis() - Jam_OutTime > 200) { + Cube_PRINT.println("[RF][Jam]Not Jamming"); + Out_flag = true; + Jam_flag = false; + //} else if (Jam_flag && Out_flag) { + } else if (Jam_flag && Out_flag) { + Cube_PRINT.print("[RF][Jam]RSSI:"); + Cube_PRINT.print(RSSI_db); + Cube_PRINT.print("dB,FREQ:"); + Cube_PRINT.print(String(freq).substring(0, 3)); + Cube_PRINT.println("Mhz"); + Out_flag = false; + Jam_flag = false; + } + } + break; + case 2://Rude + //cc1101.cmdStrobe(CC1101_STX); + digitalWrite(RF433_GDO0, HIGH); + break; + } + if (Cube_PRINT.available() > 0) { + RF_action = 0; + cc1101_config(); + Cube_PRINT.println("exit"); + } + } +} diff --git a/Software/ATmega32U4_nl/cc1101.cpp b/Software/ATmega32U4_nl/cc1101.cpp new file mode 100644 index 0000000..783f7f4 --- /dev/null +++ b/Software/ATmega32U4_nl/cc1101.cpp @@ -0,0 +1,458 @@ +#include "cc1101.h" + +//#define cc1101_Select() bitClear(PORT_SPI_SS, BIT_SPI_SS) //digitalWrite(10,HIGH) +#define cc1101_Select() digitalWrite(SS_PIN,LOW) +// Deselect (SPI) CC1101 +//#define cc1101_Deselect() bitSet(PORT_SPI_SS, BIT_SPI_SS)//digitalWrite(10,LOW) +#define cc1101_Deselect() digitalWrite(SS_PIN,HIGH) +//#define wait_Miso() while(bitRead(PORT_SPI_MISO, BIT_SPI_MISO)) +#define wait_Miso() +// Get GDO0 pin state +#define getGDO0state() bitRead(GDO0_PIN, BIT_GDO0) +// Wait until GDO0 line goes high +#define wait_GDO0_high() while(!getGDO0state()) +// Wait until GDO0 line goes low +#define wait_GDO0_low() while(getGDO0state()) + +//const byte paTable[8] = {0x00, 0xc2, 0x00, 0x00, 0xc2, 0xc2, 0xc2, 0xc2}; +const byte paTable[8] = {0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + + +CC1101::CC1101(void) +{ + +} + + +void CC1101::writeReg(byte regAddr, byte value) +{ + cc1101_Select(); // Select CC1101 + wait_Miso(); // Wait until MISO goes low + spi.send(regAddr); // Send register address + spi.send(value); // Send value + cc1101_Deselect(); // Deselect CC1101 +} + +/** + * writeBurstReg + * + * Write multiple registers into the CC1101 IC via SPI + * + * 'regAddr' Register address + * 'buffer' Data to be writen + * 'len' Data length + */ +void CC1101::writeBurstReg(byte regAddr, byte* buffer, byte len) +{ + byte addr, i; + + addr = regAddr | WRITE_BURST; // Enable burst transfer + cc1101_Select(); // Select CC1101 + wait_Miso(); // Wait until MISO goes low + spi.send(addr); // Send register address + + for(i=0 ; i + * + * This file is part of the panStamp project. + * + * panStamp is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * any later version. + * + * panStamp is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with panStamp; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * Author: Daniel Berenguer + * Creation date: 03/03/2011 + */ + +#include "cc1101_spi.h" + +/** + * init + * + * SPI initialization + */ + +void SPI::init() +{ + + pinMode(SPI_MOSI, OUTPUT); + pinMode(SPI_MISO, INPUT); + pinMode(SPI_SCK, OUTPUT); + digitalWrite(SPI_SCK, HIGH); + digitalWrite(SPI_MOSI, LOW); + + // SPI speed = clk/4 + SPCR = _BV(SPE) | _BV(MSTR); +} + +/** + * send + * + * Send byte via SPI + * + * 'value' Value to be sent + * + * Return: + * Response received from SPI slave + */ +byte SPI::send(byte value) +{ + SPDR = value; // Transfer byte via SPI + wait_Spi(); // Wait until SPI operation is terminated + + return SPDR; +} diff --git a/Software/ATmega32U4_nl/cc1101_spi.h b/Software/ATmega32U4_nl/cc1101_spi.h new file mode 100644 index 0000000..50d861e --- /dev/null +++ b/Software/ATmega32U4_nl/cc1101_spi.h @@ -0,0 +1,93 @@ +/** + * Copyright (c) 2011 panStamp + * + * This file is part of the panStamp project. + * + * panStamp is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * any later version. + * + * panStamp is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with panStamp; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * Author: Daniel Berenguer + * Creation date: 03/03/2011 + */ + +#ifndef _CC1101_SPI_H +#define _CC1101_SPI_H + +#include "Arduino.h" + +/** + * SPI pins + */ +/* +#define SPI_SS 10 // PB2 = SPI_SS +#define SPI_MOSI 11 // PB3 = MOSI +#define SPI_MISO 12 // PB4 = MISO +#define SPI_SCK 13 // PB5 = SCK +*/ + + +#define SPI_SS 10 // PB2 = SPI_SS +#define SPI_MOSI 16 // PB3 = MOSI +#define SPI_MISO 14 // PB4 = MISO +#define SPI_SCK 15 // PB5 = SCK + + +#define GDO0 2 // PD2 = INT0*/ + +#define PORT_SPI_MISO PINB +#define BIT_SPI_MISO 4 + +#define PORT_SPI_SS PORTB +#define BIT_SPI_SS 2 + +#define PORT_GDO0 PIND +#define BIT_GDO0 2 + +/** + * Macros + */ +// Wait until SPI operation is terminated +#define wait_Spi() while(!(SPSR & _BV(SPIF))) + +/** + * Class: SPI + * + * Description: + * Basic SPI class + */ +class SPI +{ + public: + /** + * init + * + * SPI initialization + */ + //void init(int ss,int MOSI,int MISO,int SCK,int GDO0); + void init(); + + /** + * send + * + * Send byte via SPI + * + * 'value' Value to be sent + * + * Return: + * Response received from SPI slave + */ + byte send(byte value); +}; +#endif diff --git a/Software/ATmega32U4_nl/ccpacket.h b/Software/ATmega32U4_nl/ccpacket.h new file mode 100644 index 0000000..57bf7fe --- /dev/null +++ b/Software/ATmega32U4_nl/ccpacket.h @@ -0,0 +1,47 @@ +#ifndef _CCPACKET_H +#define _CCPACKET_H + +#include "Arduino.h" + +/** + * Buffer and data lengths + */ +#define CC1101_BUFFER_LEN 64 +#define CC1101_DATA_LEN CC1101_BUFFER_LEN - 3 + +/** + * Class: CCPACKET + * + * Description: + * CC1101 data packet class + */ +class CCPACKET +{ + public: + /** + * Data length + */ + byte length; + + /** + * Data buffer + */ + byte data[CC1101_DATA_LEN]; + + /** + * CRC OK flag + */ + boolean crc_ok; + + /** + * Received Strength Signal Indication + */ + byte rssi; + + /** + * Link Quality Index + */ + byte lqi; +}; + +#endif diff --git a/Software/ATmega32U4_nl/em4095.cpp b/Software/ATmega32U4_nl/em4095.cpp new file mode 100644 index 0000000..07603fc --- /dev/null +++ b/Software/ATmega32U4_nl/em4095.cpp @@ -0,0 +1,467 @@ +#include "em4095.h" + +void EM4095::Start() { + for (int i = 0; i < 9; i++) { + bit1(); + } +} +void EM4095::bit1() { + //Serial.print("1"); + digitalWrite(MOD, LOW); + delayMicroseconds(delay_125); + digitalWrite(MOD, HIGH); + delayMicroseconds(delay_125); +} +void EM4095::bit0() { + //Serial.print("0"); + digitalWrite(MOD, HIGH); + delayMicroseconds(delay_125); + digitalWrite(MOD, LOW); + delayMicroseconds(delay_125); +} + + + + +void EM4095::transmit(int * data) { + Start(); + for (int i = 0; i < 11; i++) { + int flag = data[i]; + for (int a = 5; a > 0; a--) { + //((val & 0x1) << (a - 1)) + // (x[i] & (1 << a)) >> a; + if (flag & (1 << (a - 1))) { + bit1(); + } else { + bit0(); + } + } + } +// Serial.println(""); +} + + + +void EM4095::transmit(unsigned long long data) { + for (int i = 64; i > 0; i--) { + if (data >> (i-1 ) & 1) + bit1(); + else + bit0(); + } +} + + +void EM4095::simulation_bak(int vd, unsigned long id) { + int x[13]; + int l = 2; + long f = 0xf; + x[0] = (vd & 0xF0)>>4; x[1] = vd & 0x0F; + + for (int i = 7; i >= 0; i--) { + x[l] = (id & f << i * 4) >> i * 4; + l++; + } + transmit(parity_check(x)); +} + + + +void EM4095::simulation(int vd, unsigned long id) { + int x[13]; + int l = 2; + long f = 0xf; + x[0] = (vd & 0xF0)>>4; x[1] = vd & 0x0F; + for (int i = 7; i >= 0; i--) { + x[l] = (id & f << i * 4) >> i * 4; + l++; + } + int * xx=parity_check(x); + + unsigned long long NFC_DATA=0xFF80000000000000; + //unsigned long NFC_DATA_MSB=0xFF800000; + //int a=55; + unsigned long long temp; + for(int i=0;i<11;i++){ + temp=xx[i]; + temp=temp<<50-i*5;//50= - (9) - (5) + NFC_DATA+=temp; + } + transmit(NFC_DATA); +} + +int * EM4095::parity_check(int * x) +{ + + for (int i = 0; i < 10; i++) { + int val = 0; + unsigned int flag = x[i]; + while (flag) + { + val ^= flag; + flag >>= 1; + } + x[i] = x[i] << 1; + x[i] = x[i] + (val & 0x1); + } + int yval, da , val = 0; + for (int a = 4; a > 0; a--) { + //val=x[0]+x[1]+x[2]+x[3]+x[4]+x[5]+x[6]+x[7]+x[8]+x[9]+x[10]; + //val=(x[0]&(1<> a; + // Serial.print((x[i]&(1<>a,HEX); + //Serial.print(val&0x01,HEX); + //Serial.print(" "); + } + + da = ((val & 0x1) << (a - 1)); + tempdata += da; + //Serial.print(((val & 0x1) << (a - 1)), HEX); + //Serial.print(da1); + //Serial.print(" "); + val = 0; + } //Serial.println(" "); + x[10] = tempdata << 1; + tempdata = 0; + yval = 0; + + return x; +} + + +/* + +---+ + | | + --------+ + + 400 125 +*/ +void EM4095::Write_Bit1() { + digitalWrite(MOD, LOW); //GPIO_ResetBits(MOD_PORT, MOD_PIN); + delayMicroseconds(350); + digitalWrite(MOD, HIGH); + delayMicroseconds(150); + digitalWrite(MOD, LOW); +} +/* + +---+ + | | + ----+ + + 200 125 +*/ +void EM4095::Write_Bit0() { + digitalWrite(MOD, LOW); //GPIO_ResetBits(MOD_PORT, MOD_PIN); + delayMicroseconds(100); + digitalWrite(MOD, HIGH); + delayMicroseconds(150); + digitalWrite(MOD, LOW); //GPIO_ResetBits(MOD_PORT, MOD_PIN); +} +/* + +-----+ +---+ +---+ +---+ + | | | | | | | | + +-------+ +----+ +----+ + + 250 400 125 200 125 200 125 + logic display + +-----+ +---+ +---+ +---+ + | | | | | | | | + +-------+ +----+ +----+ + + 181 320 90 145 90 145 90 +*/ +void EM4095::Write_ID_Start() +{ + digitalWrite(MOD, HIGH); //GPIO_SetBits(MOD_PORT, MOD_PIN); + delayMicroseconds(240);//#Delay_us(250); + digitalWrite(MOD, LOW); //GPIO_ResetBits(MOD_PORT, MOD_PIN); + Write_Bit1(); + Write_Bit0(); + Write_Bit0(); +} + + +void EM4095::Write_ID_Block(uint32_t *ID_Data, uint8_t Data_Nun, uint8_t ID_Addr) +{ + uint32_t i; + Write_ID_Start(); + while (Data_Nun--) + { + for (i = 32; i > 0; i--) + { + if ((*ID_Data >> (i - 1)) & 0x0001) + Write_Bit1(); + else + Write_Bit0(); + } + ID_Data++; + } + for (i = 3; i > 0; i--) + { + if ((ID_Addr >> (i - 1)) & 0x01) + Write_Bit1(); + else + Write_Bit0(); + } +} + + + +unsigned long long EM4095::parity_check_write(int vd, unsigned long id) { + int x[13]; + int l = 2; + long f = 0xf; + x[0] = (vd & 0xF0) >> 4; x[1] = vd & 0x0F; + for (int i = 7; i >= 0; i--) { + x[l] = (id & f << i * 4) >> i * 4; + l++; + } + int * xx = parity_check(x); + unsigned long long NFC_DATA = 0xFF80000000000000; + unsigned long long temp; + for (int i = 0; i < 11; i++) { + temp = xx[i]; + temp = temp << 50 - i * 5; //50= - (9) - (5) + NFC_DATA += temp; + } + return NFC_DATA; + /* + unsigned long id_data_MSB=NFC_DATA>>32; + unsigned long id_data_LSB=NFC_DATA&0xffffffff; + Serial.print(id_data_MSB,HEX); + Serial.print(","); + Serial.println(id_data_LSB,HEX);*/ + //transmit(NFC_DATA); +} + + + +void EM4095::Write_ID(uint8_t WriteVD, uint32_t WriteID) +{ + uint32_t Config[2] = {0x264CB9E0, 0x00148040}; + uint32_t Password = 0x00000000; + uint32_t CardType = 0x00148040; + + //digitalWrite(SHD, LOW); //CLR_SHD + digitalWrite(SHD, LOW); //CLR_SHD + delay(36); + Write_ID_Block(Config, 2, 0x00); + delay(16); + Write_ID_Block(&Password, 1, 0x07); + delay(33); + Write_ID_Block(&CardType, 1, 0x00); + delay(16); + unsigned long long CardData = parity_check_write(WriteVD, WriteID); + uint32_t CardDataMSB = CardData >> 32; + uint32_t CardDataLSB = CardData & 0xffffffff; + + Write_ID_Block(&CardDataMSB, 1, 0x01); + delay(16); + Write_ID_Block(&CardDataLSB , 1, 0x02); + delay(16); + digitalWrite(SHD, HIGH); //SET_SHD(); + + + delay(133); + digitalWrite(SHD, LOW); + delay(133); + digitalWrite(SHD, HIGH); + digitalWrite(MOD, HIGH); + delay(100); + digitalWrite(SHD, LOW); + digitalWrite(MOD, LOW); + delay(100); + digitalWrite(SHD, HIGH); + digitalWrite(MOD, HIGH); + delay(100); + digitalWrite(SHD, LOW); + digitalWrite(MOD, LOW); + //digitalWrite(SHD, HIGH); //SET_SHD(); +} + + +bool EM4095::decodeTag(unsigned long &udata,int &ReadVd) +{ + unsigned long outtime= millis(); + + unsigned char i = 0; + unsigned short timeCount; + unsigned char timeOutFlag = 0; + unsigned char row, col; + unsigned char row_parity; + unsigned char col_parity[5]; + int dat; + unsigned char searchCount = 0; + unsigned char j; + //unsigned long udata; + + ReadVd = 0; + while (1) + { + if(millis() - outtime > 100) + return false; + + timeCount = 0; + while (0 == digitalRead(ID_OUT)) //watch for ID_OUT to go low + { + + if (timeCount >= TIMEOUT) //if we pass TIMEOUT milliseconds, break out of the loop + { + break; + } + else + { + timeCount++; + } + } + + if (timeCount >= 1200) + { + return false; + } + timeCount = 0; + + delayMicroseconds(DELAYVAL); + if (digitalRead(ID_OUT) == HIGH) + { + + for (i = 0; i < 8; i++) // 9 header bits + { + timeCount = 0; //restart counting + while (1 == digitalRead(ID_OUT)) //while DEMOD out is high + { + + if (timeCount == TIMEOUT) + { + timeOutFlag = 1; + break; + } + else + { + timeCount++; + } + } + + if (timeOutFlag) + { + break; + } + else + { + delayMicroseconds(DELAYVAL); + /* digitalWrite(PA3,HIGH); + delayMicroseconds(20); + digitalWrite(PA3,LOW);*/ + if ( 0 == digitalRead(ID_OUT) ) + { + break; + } + } + } + if (timeOutFlag) + { + timeOutFlag = 0; + return false; + } + if (i == 8) //Er zijn negen beginparameters herkend om gegevens te ontvangen + { + + /* digitalWrite(PA3, HIGH); + delayMicroseconds(20); + digitalWrite(PA3, LOW);*/ + + + timeOutFlag = 0; + timeCount = 0; + + while (1 == digitalRead(ID_OUT)) + { + if (timeCount == TIMEOUT) + { + timeOutFlag = 1; + break; + } + else + { + timeCount++; + } + + if (timeOutFlag) + { + timeOutFlag = 0; + return false; + } + } + + col_parity[0] = col_parity[1] = col_parity[2] = col_parity[3] = col_parity[4] = 0; + for (row = 0; row < 11; row++) + { + /* digitalWrite(PA3, HIGH); + delayMicroseconds(15); + digitalWrite(PA3, LOW); + */ + row_parity = 0; + j = row - 1; + for (col = 0, row_parity = 0; col < 5; col++) + { + /* digitalWrite(PA3, HIGH); + delayMicroseconds(2); + digitalWrite(PA3, LOW);*/ + delayMicroseconds(DELAYVAL); + if (digitalRead(ID_OUT)) { + dat = 1; + } else { + dat = 0; + } + if (col < 4 && row < 10 && row > 1) + { + udata = udata << 1; + udata += dat; + } else if (col < 4 && row < 2) { + ReadVd = ReadVd << 1; + ReadVd += dat; + } + + + row_parity += dat; + col_parity[col] += dat; + timeCount = 0; + + while (digitalRead(ID_OUT) == dat) + { + if (timeCount == TIMEOUT) + { + timeOutFlag = 1; + break; + } + else + timeCount++; + + } + if (timeOutFlag) + break; + } + + if (row < 10) + { + if ((row_parity & 0x01) || timeOutFlag) //Row parity + { + timeOutFlag = 1; + break; + } + } + } + if ( timeOutFlag || (col_parity[0] & 0x01) || (col_parity[1] & 0x01) || (col_parity[2] & 0x01) || (col_parity[3] & 0x01) ) //Column parity + { + timeOutFlag = 0; + return false; + } + else + { + ReadVd = ReadVd & 0xff; + //Serial.println(ReadVd); + //return (udata); + return true; + } + }//end receive data + return false; + } + } +}; diff --git a/Software/ATmega32U4_nl/em4095.h b/Software/ATmega32U4_nl/em4095.h new file mode 100644 index 0000000..ce78a66 --- /dev/null +++ b/Software/ATmega32U4_nl/em4095.h @@ -0,0 +1,39 @@ +#include "HackCube.h" +#include "Arduino.h" + +#ifndef EM4095_H +#define EM4095_H + +#define DELAYVAL 320 //384 //standard delay for manchster decode +#define TIMEOUT 1000 //standard timeout for manchester decode +#define delay_125 250 //standard timeout for manchester decode + +class EM4095{ + +public: + int vd; + int tempdata; + bool decodeTag(unsigned long &udata,int &ReadVd); + void Start(); + void bit0(); + void bit1(); + void transmit(int * data); + void transmit(unsigned long long data); + void simulation_bak(int vd, unsigned long id); + void simulation(int vd, unsigned long id); + int * parity_check(int * x); + + void Write_Bit1(); + void Write_Bit0(); + void Write_ID_Start(); + void Write_ID_Block(uint32_t *ID_Data, uint8_t Data_Nun, uint8_t ID_Addr); + unsigned long long parity_check_write(int vd, unsigned long id); + int * parity_check_write(int * x); + void Write_ID(uint8_t WriteVD, uint32_t WriteID); + + +private: + +}; + +#endif diff --git a/Software/ATmega32U4_nl/hid.h b/Software/ATmega32U4_nl/hid.h new file mode 100644 index 0000000..40192d5 --- /dev/null +++ b/Software/ATmega32U4_nl/hid.h @@ -0,0 +1,34 @@ +/* + * Analoog toetsenbordapparaat + */ +#include "Keyboard.h" + +void hid_attack() { + //if (Cube_PRINT_data[1] == 0x61) { + if (!Cube_PRINT_data.indexOf("[HID]lock")) { + Cube_PRINT.println("lock"); + Keyboard.press(KEY_LEFT_GUI); + Keyboard.press('l'); + delay(1000); + Keyboard.releaseAll(); + Keyboard.write(KEY_RETURN); + } else if (!Cube_PRINT_data.indexOf("[HID]cmatrix")) { + Keyboard.press(KEY_RIGHT_CTRL); + Keyboard.press(KEY_LEFT_ALT); + Keyboard.press('t'); + delay(200); + Keyboard.releaseAll(); + delay(1500); + Keyboard.press(KEY_F11); + delay(300); + Keyboard.releaseAll(); + delay(300); + Keyboard.print("cmatrix"); + delay(100); + Keyboard.write(KEY_RETURN); + } else { + Cube_PRINT_data[0] = ""; + Keyboard.print(Cube_PRINT_data.substring(5, Cube_PRINT_data.length())); + } + Cube_PRINT.println("hid"); +} diff --git a/Software/ATmega32U4_nl/nRF24L01.h b/Software/ATmega32U4_nl/nRF24L01.h new file mode 100644 index 0000000..5df47b0 --- /dev/null +++ b/Software/ATmega32U4_nl/nRF24L01.h @@ -0,0 +1,127 @@ +/* + Copyright (c) 2007 Stefan Engelke + Portions Copyright (C) 2011 Greg Copeland + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, copy, + modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +/* Memory Map */ +#define NRF_CONFIG 0x00 +#define EN_AA 0x01 +#define EN_RXADDR 0x02 +#define SETUP_AW 0x03 +#define SETUP_RETR 0x04 +#define RF_CH 0x05 +#define RF_SETUP 0x06 +#define NRF_STATUS 0x07 +#define OBSERVE_TX 0x08 +#define CD 0x09 +#define RX_ADDR_P0 0x0A +#define RX_ADDR_P1 0x0B +#define RX_ADDR_P2 0x0C +#define RX_ADDR_P3 0x0D +#define RX_ADDR_P4 0x0E +#define RX_ADDR_P5 0x0F +#define TX_ADDR 0x10 +#define RX_PW_P0 0x11 +#define RX_PW_P1 0x12 +#define RX_PW_P2 0x13 +#define RX_PW_P3 0x14 +#define RX_PW_P4 0x15 +#define RX_PW_P5 0x16 +#define FIFO_STATUS 0x17 +#define DYNPD 0x1C +#define FEATURE 0x1D + +/* Bit Mnemonics */ +#define MASK_RX_DR 6 +#define MASK_TX_DS 5 +#define MASK_MAX_RT 4 +#define EN_CRC 3 +#define CRCO 2 +#define PWR_UP 1 +#define PRIM_RX 0 +#define ENAA_P5 5 +#define ENAA_P4 4 +#define ENAA_P3 3 +#define ENAA_P2 2 +#define ENAA_P1 1 +#define ENAA_P0 0 +#define ERX_P5 5 +#define ERX_P4 4 +#define ERX_P3 3 +#define ERX_P2 2 +#define ERX_P1 1 +#define ERX_P0 0 +#define AW 0 +#define ARD 4 +#define ARC 0 +#define PLL_LOCK 4 +#define RF_DR 3 +#define RF_PWR 6 +#define RX_DR 6 +#define TX_DS 5 +#define MAX_RT 4 +#define RX_P_NO 1 +#define TX_FULL 0 +#define PLOS_CNT 4 +#define ARC_CNT 0 +#define TX_REUSE 6 +#define FIFO_FULL 5 +#define TX_EMPTY 4 +#define RX_FULL 1 +#define RX_EMPTY 0 +#define DPL_P5 5 +#define DPL_P4 4 +#define DPL_P3 3 +#define DPL_P2 2 +#define DPL_P1 1 +#define DPL_P0 0 +#define EN_DPL 2 +#define EN_ACK_PAY 1 +#define EN_DYN_ACK 0 + +/* Instruction Mnemonics */ +#define R_REGISTER 0x00 +#define W_REGISTER 0x20 +#define REGISTER_MASK 0x1F +#define ACTIVATE 0x50 +#define R_RX_PL_WID 0x60 +#define R_RX_PAYLOAD 0x61 +#define W_TX_PAYLOAD 0xA0 +#define W_ACK_PAYLOAD 0xA8 +#define FLUSH_TX 0xE1 +#define FLUSH_RX 0xE2 +#define REUSE_TX_PL 0xE3 +#define RF24_NOP 0xFF + +/* Non-P omissions */ +#define LNA_HCURR 0 + +/* P model memory Map */ +#define RPD 0x09 +#define W_TX_PAYLOAD_NO_ACK 0xB0 + +/* P model bit Mnemonics */ +#define RF_DR_LOW 5 +#define RF_DR_HIGH 3 +#define RF_PWR_LOW 1 +#define RF_PWR_HIGH 2 diff --git a/Software/ATmega32U4_nl/nfc.h b/Software/ATmega32U4_nl/nfc.h new file mode 100644 index 0000000..af778ad --- /dev/null +++ b/Software/ATmega32U4_nl/nfc.h @@ -0,0 +1,130 @@ +/* + * + */ +#include "em4095.h" +EM4095 EM4095; + +int NFC_VD; +int NFC_action; + +unsigned long long NFC_data; +unsigned long NFC_ID; + +unsigned long NFC_START; +unsigned long NFC_END; + +/* + * Decodeer kaartnummergegevens door de OUT-uitgangspen van de EM4095 te pollen +*/ + +void SnifferEM4100(){ +int EM4100_VD; +unsigned long EM4100_DATA; + + if (EM4095.decodeTag(EM4100_DATA, EM4100_VD)) { + if (millis() - SerialLastTime < Print_Time) { + //mySwitch.resetAvailable(); + return; + } else if (EM4100_DATA < 1) { + return; + } + Cube_PRINT.print("[NFC][read]vd:"); + Cube_PRINT.print(EM4100_VD); + Cube_PRINT.print(",data:"); + Cube_PRINT.println(EM4100_DATA); + EM4100_DATA = 0; + EM4100_VD = 0; + SerialLastTime = millis(); + } +} + +/* + * Simuleer de werking van de kaart door de EM4095 MOD pin analoge kaartkoppeling te regelen + */ + +void simulation() { + unsigned long int udata = 6834998; + EM4095.simulation(0x0c, udata); +} + +/* + * Bestuurt de EM4095 SHD- en MOD-pinnen om ze in slaapstand te brengen voor een laag stroomverbruik + */ +void NFC_Switch(String action) { + //pinMode(11,OUTPUT); + if (action == "off") { + + digitalWrite(MOD, HIGH); + digitalWrite(SHD, HIGH); + //digitalWrite(11,HIGH); + } else if (action == "on") { + digitalWrite(MOD, LOW); + digitalWrite(SHD, LOW); + //digitalWrite(12,LOW); + } else { + } +} +bool NFC_Action() { + return !digitalRead(MOD); +} + +/* + * Nummerkaartprogramma stralen + */ +void NFC_attack(int vd, unsigned long start, unsigned long end ) { + //NFC_ID=start; + // 35 Ms / count;15==500MS + for (int i = 0; i < 15; i++) { + EM4095.simulation(NFC_VD, NFC_ID); + } + int NFC_porg = map(NFC_ID, start, end, 0, 100); + if (NFC_porg > 100) + NFC_porg = 100; + Cube_PRINT.print("[NFC][progress]"); + Cube_PRINT.println(NFC_porg); + //Serial.println(NFC_ID); + if (NFC_ID == end ) + NFC_action = 0; + + NFC_ID++; +} + +/* + * Simuleer / vernietig kaarten uit de EM4100-serie volgens de instructies + */ +void AttackEM4100(){ + while (NFC_action) { + switch (NFC_action) { + case 1: + EM4095.simulation(NFC_VD, NFC_ID); + break; + case 2: + NFC_attack(NFC_VD, NFC_START, NFC_END); + break; + } + if (Cube_PRINT.available() > 0) { + NFC_action = 0; + Cube_PRINT.println("exit"); + } + } +} + +//String nfcdata="1111111110000011000000000000001100100010100110111001100110010000"; +// +//unsigned long long nfcdata = 0xFF830003229b9990; +//0006834998 + + + +void nfcbit1() { + digitalWrite(MOD, LOW); + delayMicroseconds(250); + digitalWrite(MOD, HIGH); + delayMicroseconds(250); +} +void nfcbit0() { + digitalWrite(MOD, HIGH); + delayMicroseconds(250); + digitalWrite(MOD, LOW); + delayMicroseconds(250); +} diff --git a/Software/ATmega32U4_nl/printf.h b/Software/ATmega32U4_nl/printf.h new file mode 100644 index 0000000..d54e661 --- /dev/null +++ b/Software/ATmega32U4_nl/printf.h @@ -0,0 +1,59 @@ +/* + Copyright (C) 2011 J. Coliz + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + */ + /* Galileo support from spaniakos */ + +/** + * @file printf.h + * + * Setup necessary to direct stdout to the Arduino Serial library, which + * enables 'printf' + */ + +#ifndef __PRINTF_H__ +#define __PRINTF_H__ + +#if defined (ARDUINO) && !defined (__arm__) && !defined(__ARDUINO_X86__) + +int serial_putc( char c, FILE * ) +{ + Serial.write( c ); + + return c; +} + +void printf_begin(void) +{ + fdevopen( &serial_putc, 0 ); +} + +#elif defined (__arm__) + +void printf_begin(void){} + +#elif defined(__ARDUINO_X86__) +int serial_putc( char c, FILE * ) +{ + Serial.write( c ); + + return c; +} + +void printf_begin(void) +{ + //JESUS - For reddirect stdout to /dev/ttyGS0 (Serial Monitor port) + stdout = freopen("/dev/ttyGS0","w",stdout); + delay(500); + printf("redirecting to Serial..."); + + //JESUS ----------------------------------------------------------- +} +#else +#error This example is only for use on Arduino. +#endif // ARDUINO + +#endif // __PRINTF_H__ diff --git a/Software/ATmega32U4_nl/rf.h b/Software/ATmega32U4_nl/rf.h new file mode 100644 index 0000000..c26b129 --- /dev/null +++ b/Software/ATmega32U4_nl/rf.h @@ -0,0 +1,712 @@ + +#include "HackCube.h" + + +#include "RCSwitch.h"//https://github.com/sui77/rc-switch +RCSwitch mySwitch = RCSwitch(); + + +#include "cc1101.h" +CC1101 cc1101; + +void setfreqx(unsigned long int freq) { + unsigned long freqnum = freq / 396.734569; + //Cube_PRINT.println(freqnum,HEX); + byte freqx[3]; + freqx[0] = freqnum; + freqx[1] = freqnum >> 8; + freqx[2] = freqnum >> 16; + //Cube_PRINT.print( freqx[2],HEX );Cube_PRINT.print(" " );Cube_PRINT.print( freqx[1],HEX);Cube_PRINT.print(" " );Cube_PRINT.print( freqx[0],HEX);Cube_PRINT.println(" " ); + cc1101.writeReg(CC1101_FREQ2, freqx[2]); + cc1101.writeReg(CC1101_FREQ1, freqx[1]); + cc1101.writeReg(CC1101_FREQ0, freqx[0]); +} +void setfreqx(int FREQ2, int FREQ1, int FREQ0) { + cc1101.writeReg(CC1101_FREQ2, FREQ2); + cc1101.writeReg(CC1101_FREQ1, FREQ1); + cc1101.writeReg(CC1101_FREQ0, FREQ0); +} + +void cc1101_config() { + cc1101.SS_PIN = RF433_CS; + cc1101.init(); + //cc1101.setSyncWord(syncWord); + setfreqx(freq_cc1101); + cc1101.disableAddressCheck(); + //cc1101.cmdStrobe(CC1101_SRX); + cc1101.writeReg(CC1101_IOCFG2, 0x0d); + + // cc1101.writeReg(CC1101_MDMCFG4, 0xF7); + //cc1101.writeReg(CC1101_MDMCFG4, 0x87);//RFB 200K + cc1101.writeReg(CC1101_MDMCFG4, 0x07);//RFB 200K + cc1101.writeReg(CC1101_MDMCFG3, 0x93); + //cc1101.writeReg(CC1101_AGCCTRL2, 0xB0); + cc1101.cmdStrobe(CC1101_SRX); //F5 43 +} + +void cc1101_RXconfig() { + cc1101.SS_PIN = RF433_CS; + cc1101.writeReg(CC1101_MDMCFG4, 0x07);//RFB 200K + cc1101.writeReg(CC1101_MDMCFG3, 0x93); + cc1101.cmdStrobe(CC1101_SRX); //F5 43 +} + + + +#include "attack.h" +#include "rf_rollcode.h" + +void cc1101_Setup() { + //class:fixed,freq:315 + String set_class = Cube_PRINT_data.substring(Cube_PRINT_data.indexOf("class") + 6, Cube_PRINT_data.indexOf(",freq")); + freq_cc1101 = strtoul(Cube_PRINT_data.substring(Cube_PRINT_data.indexOf("freq") + 5, Cube_PRINT_data.length()).c_str(), NULL, 10); + + if (set_class == "fixed") { + rf_class = 1; + detachInterrupt(1); + cc1101.cmdStrobe(CC1101_SIDLE); + setfreqx(freq_cc1101); + cc1101.cmdStrobe(CC1101_SRX); + mySwitch.enableReceive(1);//Stel de mySwitch-onderbrekingspin in om het vaste codesignaal te ontvangen + Cube_PRINT.println("*RF_sniffer_fixed"); + + } else if (set_class == "keeloq") { + rf_class = 2; + detachInterrupt(1); + cc1101.cmdStrobe(CC1101_SIDLE); + setfreqx(freq_cc1101); + cc1101.cmdStrobe(CC1101_SRX); + Hackradio.enableReceive(1);//Stel de onderbrekingspin in om het rolling codesignaal te ontvangen + Cube_PRINT.println("*RF_sniffer_Keeloq"); + } +} + +void RF_Switch(String action) { + //pinMode(11,OUTPUT); + if (action == "off") { + digitalWrite(RF_EN, LOW); + Cube_PRINT.println("*RF_Power off"); + } else if (action == "on") { + digitalWrite(RF_EN, HIGH); + Cube_PRINT.println("*RF_Power on"); + cc1101_config(); + } +} + + +void RF433_Setup() { + cc1101.SS_PIN = RF433_CS; + cc1101.init(); + //byte syncWord[2] = {0x00, 0x00}; + //cc1101.setSyncWord(syncWord); + + cc1101.setCarrierFreq(CFREQ_433); + + //cc1101.disableAddressCheck(); + cc1101.cmdStrobe(CC1101_SRX); + cc1101.writeReg(CC1101_IOCFG2, 0x0d); + //cc1101.writeReg(CC1101_AGCCTRL2, 0xB0); + //cc1101.writeReg(CC1101_MDMCFG4, 0xc8); + cc1101.writeReg(CC1101_MDMCFG4, 0xc8); + cc1101.writeReg(CC1101_MDMCFG3, 0x93); +} + + + + + + +void RF315_Setup() { + cc1101.SS_PIN = RF315_CS; + cc1101.init(); + //byte syncWord[2] = {0x00, 0x00}; + //cc1101.setSyncWord(syncWord); + cc1101.setCarrierFreq(CFREQ_433); + //cc1101.disableAddressCheck(); + cc1101.cmdStrobe(CC1101_SRX); + cc1101.writeReg(CC1101_IOCFG2, 0x0d); + //cc1101.writeReg(CC1101_AGCCTRL2, 0xB0); + cc1101.writeReg(CC1101_MDMCFG4, 0xc8); + //cc1101.writeReg(CC1101_MDMCFG3, 0x93); +} + + +void Fixed_Config() { + cc1101.SS_PIN = RF315_CS; + cc1101.init(); + byte syncWord[2] = {0xFF, 0xFF}; + // cc1101.setSyncWord(syncWord); + cc1101.setSyncWord(syncWord); + //cc1101.setCarrierFreq(CFREQ_315); + setfreqx(freq_cc1101); + cc1101.disableAddressCheck(); + cc1101.cmdStrobe(CC1101_STX); + cc1101.writeReg(CC1101_IOCFG2, 0x0d); +} + + +void Fixed_Config_433() { + cc1101.SS_PIN = RF315_CS; + cc1101.init(); + byte syncWord[2] = {0xFF, 0xFF}; + cc1101.setSyncWord(syncWord); + //cc1101.setCarrierFreq(CFREQ_433); + setfreqx(433750000); + cc1101.disableAddressCheck(); + cc1101.cmdStrobe(CC1101_STX); + cc1101.writeReg(CC1101_IOCFG2, 0x0d); + //cc1101.writeReg(CC1101_AGCCTRL2, 0xB0); +} + + +void Fixed_Config_433_leftdoor() { + cc1101.SS_PIN = RF315_CS; + cc1101.init(); + byte syncWord[2] = {0xFF, 0xFF}; + cc1101.setSyncWord(syncWord); + //cc1101.setCarrierFreq(CFREQ_433); + setfreqx(434010000); + cc1101.disableAddressCheck(); + cc1101.cmdStrobe(CC1101_STX); + cc1101.writeReg(CC1101_IOCFG2, 0x0d); + //cc1101.writeReg(CC1101_AGCCTRL2, 0xB0); +} + + +void Fixed_Config_433_RX() { + cc1101.SS_PIN = RF315_CS; + cc1101.init(); + setfreqx(433750000); + cc1101.disableAddressCheck(); + cc1101.writeReg(CC1101_IOCFG2, 0x0d); + cc1101.writeReg(CC1101_MDMCFG4, 0x07);//RFB 200K + cc1101.writeReg(CC1101_MDMCFG3, 0x93); + cc1101.cmdStrobe(CC1101_SRX); //F5 43 +} + + + + +/* + LigthBar + Freq 315 +*/ +int Ligth_Transmitpin = RF315_GDO0; +void Ligth_Config_315() { + cc1101.SS_PIN = RF315_CS; + cc1101.init(); + byte syncWord[2] = {0xFF, 0xFF}; + cc1101.setSyncWord(syncWord); + setfreqx(315000000); + cc1101.disableAddressCheck(); + cc1101.cmdStrobe(CC1101_STX); + cc1101.writeReg(CC1101_IOCFG2, 0x0d); + +} + +void ligth_bar_header() { + digitalWrite(RF315_GDO0, HIGH); + delayMicroseconds(1330); + digitalWrite(RF315_GDO0, LOW); + delayMicroseconds(650); + + for (int i = 0; i < 9; i++) { + digitalWrite(RF315_GDO0, HIGH); + delayMicroseconds(650); + digitalWrite(RF315_GDO0, LOW); + delayMicroseconds(325); + } +} + +void ligth_bar_bit_0() { + digitalWrite(RF315_GDO0, HIGH); + delayMicroseconds(240); + digitalWrite(RF315_GDO0, LOW); + delayMicroseconds(700); + +} + +void ligth_bar_bit_1() { + digitalWrite(RF315_GDO0, HIGH); + delayMicroseconds(650); + digitalWrite(RF315_GDO0, LOW); + delayMicroseconds(286); + +} + +void LigthBar_Transmit(unsigned long data) { + //Serial.println(data,BIN); + + delay(2); + int replay = 5; + for (int i = 0; i < replay; i++) { + ligth_bar_header(); + for (int a = 15; a > 0; a--) { + if (data >> a - 1 & 1 == 1) { + ligth_bar_bit_1(); + } else { + ligth_bar_bit_0(); + } + } + } +} +//[RF][Transmit]LigthBar,freq:315,data:2600 +void RF_LigthBar() { + unsigned int freq = strtoul(Cube_PRINT_data.substring(Cube_PRINT_data.indexOf("freq") + 5, Cube_PRINT_data.indexOf(",data")).c_str(), NULL, 10); + unsigned long data = strtoul(Cube_PRINT_data.substring(Cube_PRINT_data.indexOf("data:") + 5, Cube_PRINT_data.length()).c_str(), NULL, 16); + + if (freq == 315) { + Ligth_Config_315(); + } + LigthBar_Transmit(data); + Cube_PRINT.print("*Transmit LigthBar "); + Cube_PRINT.print("Freq:"); + Cube_PRINT.print(freq); + Cube_PRINT.print(",Data:"); + Cube_PRINT.println(data, HEX); + cc1101_config(); +} + + + + + + +int Fixed_Transmitpin = RF315_GDO0; + +//void Fixed_Bit1() { +// //Cube_PRINT.print("1"); +// digitalWrite(Fixed_Transmitpin, HIGH); +// delayMicroseconds(820); +// digitalWrite(Fixed_Transmitpin, LOW); +// delayMicroseconds(287); +// digitalWrite(Fixed_Transmitpin, LOW); +//} +//void Fixed_Bit0() { +// //Cube_PRINT.print("0"); +// digitalWrite(Fixed_Transmitpin, HIGH); +// delayMicroseconds(287); +// digitalWrite(Fixed_Transmitpin, LOW); +// //delayMicroseconds(670); +// delayMicroseconds(820); +// digitalWrite(Fixed_Transmitpin, LOW); +//} + +/* + void Fixed_Bit1() { + //Cube_PRINT.print("1"); + digitalWrite(Fixed_Transmitpin, HIGH); + delayMicroseconds(900); + digitalWrite(Fixed_Transmitpin, LOW); + delayMicroseconds(300); + digitalWrite(Fixed_Transmitpin, LOW); + } + void Fixed_Bit0() { + //Cube_PRINT.print("0"); + digitalWrite(Fixed_Transmitpin, HIGH); + delayMicroseconds(300); + digitalWrite(Fixed_Transmitpin, LOW); + //delayMicroseconds(670); + delayMicroseconds(900); + digitalWrite(Fixed_Transmitpin, LOW); + }*/ + + +void Fixed_Bit1() { + //Cube_PRINT.print("1"); + digitalWrite(Fixed_Transmitpin, HIGH); + delayMicroseconds(915); + digitalWrite(Fixed_Transmitpin, LOW); + delayMicroseconds(305); + digitalWrite(Fixed_Transmitpin, LOW); +} +void Fixed_Bit0() { + //Cube_PRINT.print("0"); + digitalWrite(Fixed_Transmitpin, HIGH); + delayMicroseconds(305); + digitalWrite(Fixed_Transmitpin, LOW); + //delayMicroseconds(670); + delayMicroseconds(915); + digitalWrite(Fixed_Transmitpin, LOW); +} + + + + + +void Fixed_Bit1_Class1() { + digitalWrite(Fixed_Transmitpin, HIGH); + delayMicroseconds(203); + digitalWrite(Fixed_Transmitpin, LOW); + delayMicroseconds(58); + digitalWrite(Fixed_Transmitpin, LOW); +} +void Fixed_Bit0_Class1() { + digitalWrite(Fixed_Transmitpin, HIGH); + delayMicroseconds(58); + digitalWrite(Fixed_Transmitpin, LOW); + delayMicroseconds(203); + digitalWrite(Fixed_Transmitpin, LOW); +} + + + +void Fixed_Bit1_1() { + //Cube_PRINT.print("1"); + digitalWrite(Fixed_Transmitpin, HIGH); + delayMicroseconds(975); + digitalWrite(Fixed_Transmitpin, LOW); + delayMicroseconds(325); + digitalWrite(Fixed_Transmitpin, LOW); +} +void Fixed_Bit0_1() { + //Cube_PRINT.print("0"); + digitalWrite(Fixed_Transmitpin, HIGH); + delayMicroseconds(325); + digitalWrite(Fixed_Transmitpin, LOW); + delayMicroseconds(975); + digitalWrite(Fixed_Transmitpin, LOW); +} + + + +void Class2_Transmit(unsigned long data, int Func) { + + for (int a = 20; a > 0; a--) { + if (data >> a - 1 & 1 == 1) { + Fixed_Bit1(); + } else { + Fixed_Bit0(); + } + + } + for (int l = 4; l > 0; l--) { + if (Func >> l - 1 & 1 == 1) { + Fixed_Bit1(); + } else { + Fixed_Bit0(); + } + } + Fixed_Bit0(); + //digitalWrite(Fixed_Transmitpin,LOW); + //Cube_PRINT.println(""); +} + + +void Class2_Attack(unsigned long s, unsigned long e, int func = 0x9, long freq = 315, bool Progress = true) { + unsigned long EndNum = e + 1; + unsigned long StartlNum = s; + unsigned long Num = StartlNum; + if (freq == 315) { + Fixed_Config(); + //Serial.println("Transmit 315"); + } else if (freq == 433) { + Fixed_Config_433_leftdoor(); + //Serial.println("Transmit 433"); + } else { + Serial.print(freq); + //Serial.println("Transmit ???"); + } + if (Progress) { + //cc1101.PrintConfig(); + Serial.print("Start:"); + Serial.print(StartlNum); + Serial.print(",End:"); + Serial.print(EndNum); + Serial.print(",Func:"); + Serial.println(func); + } + + + while (Num < EndNum) { + + for (int i = 0; i < 8; i++) { + Class2_Transmit(Num, func); + delay(12); + } + delay(80); + Num++; + if (Progress) { + int attack_progress = map(Num, StartlNum, EndNum, 0, 100); + Cube_PRINT.print("[RF][Progress]"); + Cube_PRINT.println(attack_progress); + } + //delay(100); + } + if (Cube_PRINT.available() > 0) { + + cc1101_config(); + RF_action = 0; + } + //cc1101_config(); + //Fixed_Config_433_RX(); + //Cube_PRINT.println("END"); +} + +void Class2_Send() { + for (int i = 0; i < 2; i++) { + Class2_Transmit(0x017A5, 0x9); + delay(12); + } + +} + +/* + void Class1_Transmit(unsigned long data) { + + for (int a = 16; a > 0; a--) { + if (data >> a - 1 & 1 == 1) { + //Fixed_Bit1_Class1(); + Fixed_Bit1_1(); + } else { + //Fixed_Bit0_Class1(); + Fixed_Bit0_1(); + } + + } + Fixed_Bit1_1(); Fixed_Bit1_1(); + Fixed_Bit1_1(); Fixed_Bit1_1(); + Fixed_Bit1_1(); Fixed_Bit1_1(); + Fixed_Bit1_1(); Fixed_Bit1_1(); + Fixed_Bit0_1(); + //Cube_PRINT.println(""); + } + + + void Class1_Attack() { + unsigned int EndNum = 0x5486; + unsigned int Cube_PRINTNum = 0x5356; + unsigned int Num = Cube_PRINTNum; + + while (Cube_PRINTNum < EndNum) { + for (int i = 0; i < 2; i++) { + Class1_Transmit(Cube_PRINTNum); + delay(11); + } + Cube_PRINTNum ++; + } + } +*/ + + + + + + +/* + RF24l01 +*/ + + + +byte command_fly[6] = {0x50, 0x03, 0x00, 0x03, 0x00}; +byte command_s[6] = {0x50, 0x03, 0x00, 0x01, 0x00}; +byte command_s1[6] = {0x50, 0x03, 0x00, 0x02, 0x00}; + +byte command_d[6] = {0x50, 0x03, 0x00, 0x04, 0x00}; +byte command_RBT[11] = {0x03, 0x08, 0xdc, 0x05, 0xdc, 0x05, 0xdc, 0x05, 0xdc, 0x05}; +byte command[4] = {0x40, 0x01, 0xff}; + +byte command_ulock[4] = {0x01, 0x01, 0xA1}; + + +#include +#include "nRF24L01.h" +#include "RF24.h"//https://github.com/nRF24/RF24 +#include "printf.h" + +RF24 radio(nRF_CE, nRF_CS_1); + +#define csn(a) digitalWrite(nRF_CS, a) +#define ce(a) digitalWrite(nRF_CE, a) +uint8_t n(uint8_t reg, uint8_t value) +{ + uint8_t status; + ce(HIGH); + status = SPI.transfer( W_REGISTER | ( REGISTER_MASK & reg ) ); + SPI.transfer(value); + ce(LOW); + return status; +} + +void rf24l01_Setup() { + printf_begin(); + radio.begin(); + radio.setAutoAck(true); + radio.setDataRate(RF24_250KBPS);// RF24_2MBPS + radio.setPayloadSize(32); + radio.setChannel(0x02); + radio.setAddressWidth(5); + radio.openWritingPipe(0x123456789aULL); + radio.write_register(0x04, 0x53); + radio.setCRCLength(RF24_CRC_16); + radio.enableAckPayload(); + radio.enableDynamicAck(); + radio.stopListening(); + //radio.write(command, 3); + printf_begin(); + radio.printDetails(); + +} + + +void rf24l01_SnifferSetup() +{ + printf_begin(); + radio.begin(); + radio.setAutoAck(false); + //radio.setPALevel(RF24_PA_MIN); + //radio.setDataRate(RF24_250KBPS);// RF24_2MBPS + radio.setDataRate(RF24_250KBPS); + radio.setPayloadSize(32); + radio.setChannel(0x02); + radio.setAddressWidth(5); + radio.openReadingPipe(0, 0x123456789aULL); + radio.write_register(0x00, 0x0E); + radio.write_register(0x01, 0x00); + radio.write_register(0x02, 0x03); + radio.write_register(0x03, 0x03); + radio.write_register(0x04, 0x53); + radio.write_register(0x10, 0x4f); + radio.disableCRC(); + radio.enableAckPayload(); + radio.setCRCLength(RF24_CRC_16); + radio.startListening(); + radio.printDetails(); + //radio.print_config(); + +} + + + +void rf24Sniffer() { + if ( radio.available() ) + { + if (millis() - SerialLastTime < Print_Time) { + return; + } + SerialLastTime = millis(); + Cube_PRINT.print("c"); + Cube_PRINT.print("freq:2.42Ghz;protocol:rf24l01;modulation:fsk;data:"); + //Cube_PRINT.println("Test"); + byte command[32]; + radio.read( command, 5); + for (int i = 0; i < 8; i++) { + Cube_PRINT.print(command[i], HEX); + //Cube_PRINT.print(" "); + //PrintHex8(command[i]); + } + Cube_PRINT.println(""); + //byte command[32]; + ///Cube_PRINT.println(radio.Reader(command),HEX); + delay(200); + } +} + +String Sdata; + +void rfTransmit_Cube_PRINT() { + while (Cube_PRINT.available() > 0) { + Sdata += char(Cube_PRINT.read()); + delay(4); + } + if (Sdata.length() > 0) { + if (Sdata == "w") { + /* + radio.write(command_RBT, 10); + delay(100); + //command_ulock + radio.write(command_s, 5); + delay(200); + //radio.write(command_s1, 5); + + delay(200); + radio.write(command_RBT, 10); + delay(100); + radio.write(command, 3); + // radio.write(command_ulock, 3); + */ + Cube_PRINT.println("up"); + delay(100); + radio.write(command_fly, 5); + } else if (Sdata == "s") { + Cube_PRINT.println("Down"); + radio.write(command_d, 5); + delay(10); + radio.write(command_d, 5); + delay(10); + } + Sdata = ""; + } +} + + + + + + +void SnifferFixedCode() { + if (mySwitch.available()) { + if (millis() - SerialLastTime < Print_Time) { + mySwitch.resetAvailable(); + return; + } + Cube_PRINT.print("[RF][Sniffer]freq:"); + Cube_PRINT.print(String(freq_cc1101).substring(0, 3)); + Cube_PRINT.print(",protocol:Fixed-"); + Cube_PRINT.print(mySwitch.getReceivedProtocol()); + Cube_PRINT.print(",modulation:ask,func:"); + Cube_PRINT.print(mySwitch.getReceivedValue() & 0xf, HEX); + Cube_PRINT.print(",data:"); + Cube_PRINT.println(mySwitch.getReceivedValue() >> 4, HEX); + //String data1=String(mySwitch.getReceivedValue()>>4); + //Cube_PRINT.println(strtoul(data1.c_str(),NULL,16)); + mySwitch.resetAvailable(); + SerialLastTime = millis(); + } +} + +void RF_Transmit() { + long freq = strtoul(Cube_PRINT_data.substring(14, 17).c_str(), NULL, 10); + int func = strtoul(Cube_PRINT_data.substring(18, 19).c_str(), NULL, 16); + long Serialnumber = strtoul(Cube_PRINT_data.substring(20, Cube_PRINT_data.length()).c_str(), NULL, 16); + if (freq == 315) { + Fixed_Config(); + //Serial.println("315Transmit"); + } else if (freq == 433) { + Fixed_Config_433_leftdoor(); + //Serial.println("433Transmit"); + } + for (int i = 0; i < 8; i++) { + Class2_Transmit(Serialnumber, func); + delay(9); + } + + Cube_PRINT.print("*Transmit "); + Cube_PRINT.print("Freq:"); + Cube_PRINT.print(freq); + Cube_PRINT.print("Func:"); + Cube_PRINT.print(func, HEX); + Cube_PRINT.print("Data:"); + Cube_PRINT.println(Serialnumber, HEX); + cc1101_config(); +} + +void RF_Attack() { + String freq = Cube_PRINT_data.substring(Cube_PRINT_data.indexOf("freq") + 5, Cube_PRINT_data.indexOf(",start")); + String start = Cube_PRINT_data.substring(Cube_PRINT_data.indexOf("start") + 6, Cube_PRINT_data.indexOf(",end")); + String end = Cube_PRINT_data.substring(Cube_PRINT_data.indexOf("end") + 4, Cube_PRINT_data.indexOf(",func")); + String func = Cube_PRINT_data.substring(Cube_PRINT_data.indexOf("func") + 5, Cube_PRINT_data.length()); + + long rffreq = strtoul(freq.c_str(), NULL, 10); + long rfstart = strtoul(start.c_str(), NULL, 16); + long rfend = strtoul(end.c_str(), NULL, 16); + int rffunc = strtoul(func.c_str(), NULL, 16); + + Class2_Attack(rfstart, rfend, rffunc, rffreq); + cc1101_config(); +} + + + + diff --git a/Software/ATmega32U4_nl/rf_rollcode.h b/Software/ATmega32U4_nl/rf_rollcode.h new file mode 100644 index 0000000..20e56c2 --- /dev/null +++ b/Software/ATmega32U4_nl/rf_rollcode.h @@ -0,0 +1,108 @@ +#include "HackCube.h" +/* + CC1101 +*/ + + +//#include "cc1101.h" +//CC1101 cc1101; + + +void RF433_Setup_rollcode() { + cc1101.SS_PIN = RF433_CS; + cc1101.init(); + //byte syncWord[2] = {0x00, 0x00}; + //cc1101.setSyncWord(syncWord); + //freq_cc1101=433920000; + setfreqx(freq_cc1101); + //cc1101.setCarrierFreq(CFREQ_433); + + //cc1101.disableAddressCheck(); + cc1101.cmdStrobe(CC1101_SRX); + cc1101.writeReg(CC1101_IOCFG2, 0x0d); + //cc1101.writeReg(CC1101_AGCCTRL2, 0xB0); + //cc1101.writeReg(CC1101_MDMCFG4, 0xc8); + //cc1101.writeReg(CC1101_MDMCFG4, 0xc8); + //cc1101.writeReg(CC1101_MDMCFG3, 0x93); + + cc1101.writeReg(CC1101_MDMCFG4, 0x07);//RFB 200K + cc1101.writeReg(CC1101_MDMCFG3, 0x93); +} + +/* + Keeloq keyfob attack +*/ + +#include +#include +#include + + +typedef unsigned long u32; +typedef unsigned long long u64; +uint64_t key = 0x7d093b66b31c374a; +#define KeeLoq_NLF 0x3A5C742E +#define bit(x,n) (((x)>>(n))&1) +#define g5(x,a,b,c,d,e) (bit(x,a)+bit(x,b)*2+bit(x,c)*4+bit(x,d)*8+bit(x,e)*16) +uint32_t KeeLoq_Encrypt (const uint32_t data, const uint64_t key) +{ + uint32_t x = data, r; + for (r = 0; r < 528; r++) { + x = (x >> 1) ^ ((bit(x, 0)^bit(x, 16) ^ (uint32_t)bit(key, r & 63)^bit(KeeLoq_NLF, g5(x, 1, 9, 20, 26, 31))) << 31); + } + return x; +} +uint32_t KeeLoq_Decrypt (const uint32_t data, const uint64_t key) +{ + uint32_t x = data, r; + for (r = 0; r < 528; r++) { + x = (x << 1)^bit(x, 31)^bit(x, 15) ^ (uint32_t)bit(key, (15 - r) & 63)^bit(KeeLoq_NLF, g5(x, 0, 8, 19, 25, 30)); + } + return x; +} + + +/* + receive Keeloq data +*/ +#include "HackRadio.h" +HackRadio Hackradio = HackRadio(); + +void SnifferRollcode() { + if (Hackradio.available()) { + + detachInterrupt(RF315_att); + // if(mySwitch.getsn()=="39182da"){ + // Cube_PRINT.println("* Receive"); + unsigned long rfdata = strtoul(Hackradio.getkey().c_str(), NULL, 16); + //uint32_t datadc = KeeLoq_Decrypt(rfdata, key); + Cube_PRINT.print("[RF][Sniffer]"); + Cube_PRINT.print("freq:"); + Cube_PRINT.print(String(freq_cc1101).substring(0, 3)); + Cube_PRINT.print(",protocol:keeloq,modulation:ask,"); + Cube_PRINT.print("data:"); + Cube_PRINT.print(Hackradio.getkey()); + Cube_PRINT.print(",SerialNumber:"); + Cube_PRINT.print(Hackradio.getsn()); + /* Cube_PRINT.print(" Func:"); + Cube_PRINT.println(""); + Cube_PRINT.print("Decrypt:"); + Cube_PRINT.print(datadc, HEX); + Cube_PRINT.print("-->Func:"); + unsigned int Func = datadc >> 28; + //Func=Func<<28; + Cube_PRINT.print(Func, HEX); + Cube_PRINT.print(" Distinguish Code:"); + uint32_t Distinguish = datadc << 6; + Distinguish = Distinguish >> 22; + Cube_PRINT.print(Distinguish, HEX); + Cube_PRINT.print(" Sync Counter Value:"); + uint32_t SyncCounterValue = datadc << 16; + SyncCounterValue = SyncCounterValue >> 16; + Cube_PRINT.print(SyncCounterValue, HEX); + //u8g.drawRFrame(10,12, 30,20, 5);*/ + Cube_PRINT.println(""); + Hackradio.resetAvailable(); + Hackradio.enableReceive(RF315_att); + } +} diff --git a/Software/ESP8266_nl/APScan.cpp b/Software/ESP8266_nl/APScan.cpp new file mode 100644 index 0000000..8438650 --- /dev/null +++ b/Software/ESP8266_nl/APScan.cpp @@ -0,0 +1,304 @@ +#include "APScan.h" + +APScan::APScan() { + +} + +bool APScan::start() { + if (debug) { + Serial.println("starting AP scan..."); + Serial.println("MAC - Ch - RSSI - Encrypt. - SSID - Hidden");// - Vendor"); + } + aps._clear(); + results = 0; + for (int i = 0; i < maxAPScanResults; i++){ + selected[i] = false; + String("").toCharArray(names[i], 33); + } + results = WiFi.scanNetworks(false, true); // lets scanNetworks return hidden APs. (async = false & show_hidden = true) + if(results > maxAPScanResults) results = maxAPScanResults; + + if (debug) Serial.println("Scan results: "+(String)results); + + for (int i = 0; i < results && i < maxAPScanResults; i++) { + Mac _ap; + _ap.set(WiFi.BSSID(i)[0], WiFi.BSSID(i)[1], WiFi.BSSID(i)[2], WiFi.BSSID(i)[3], WiFi.BSSID(i)[4], WiFi.BSSID(i)[5]); + aps.add(_ap); + channels[i] = WiFi.channel(i); + rssi[i] = WiFi.RSSI(i); + encryption[i] = WiFi.encryptionType(i); + hidden[i] = WiFi.isHidden(i); + String _ssid = WiFi.SSID(i); + _ssid.toCharArray(names[i], 33); + //data_getVendor(WiFi.BSSID(i)[0],WiFi.BSSID(i)[1],WiFi.BSSID(i)[2]).toCharArray(vendors[i],9); + if (debug) { + Serial.print((String)i); + Serial.print(" - "); + _ap._print(); + Serial.print(" - "); + Serial.print(channels[i]); + Serial.print(" - "); + Serial.print(rssi[i]); + Serial.print(" - "); + Serial.print(getEncryption(encryption[i])); + Serial.print(" - "); + Serial.print(names[i]); + Serial.print(" - "); + Serial.print(hidden[i]); + //Serial.print(" - "); + //Serial.print(vendors[i]); + Serial.println(); + } + } + + //for debugging the APScan crash bug + /* + if(debug){ + for(int i=results;i