fixed crlf for project

This commit is contained in:
Henrik Ekblad
2014-03-07 21:17:56 +01:00
parent 586a4d6239
commit c1441dca4a
62 changed files with 6964 additions and 6964 deletions
+325 -325
View File
@@ -1,325 +1,325 @@
:100000000C9463000C948B000C948B000C948B006C :100000000C9463000C948B000C948B000C948B006C
:100010000C948B000C948B000C948B000C948B0034 :100010000C948B000C948B000C948B000C948B0034
:100020000C948B000C948B000C948B000C948B0024 :100020000C948B000C948B000C948B000C948B0024
:100030000C948B000C948B000C948B000C948B0014 :100030000C948B000C948B000C948B000C948B0014
:100040000C948F050C948B000C9423060C948B005D :100040000C948F050C948B000C9423060C948B005D
:100050000C948B000C948B000C948B000C948B00F4 :100050000C948B000C948B000C948B000C948B00F4
:100060000C948B000C948B000000000024002700EF :100060000C948B000C948B000000000024002700EF
:100070002A0000000000250028002B0000000000DE :100070002A0000000000250028002B0000000000DE
:1000800023002600290004040404040404040202DA :1000800023002600290004040404040404040202DA
:100090000202020203030303030301020408102007 :100090000202020203030303030301020408102007
:1000A0004080010204081020010204081020000012 :1000A0004080010204081020010204081020000012
:1000B0000007000201000003040600000000000029 :1000B0000007000201000003040600000000000029
:1000C000000090043B0711241FBECFEFD8E0DEBF35 :1000C000000090043B0711241FBECFEFD8E0DEBF35
:1000D000CDBF11E0A0E0B1E0E6EFF3E102C0059092 :1000D000CDBF11E0A0E0B1E0E6EFF3E102C0059092
:1000E0000D92AA33B107D9F712E0AAE3B1E001C03B :1000E0000D92AA33B107D9F712E0AAE3B1E001C03B
:1000F0001D92A13FB107E1F710E0C6ECD0E004C0CB :1000F0001D92A13FB107E1F710E0C6ECD0E004C0CB
:100100002297FE010E94F509C23CD107C9F70E945F :100100002297FE010E94F509C23CD107C9F70E945F
:100110001C060C94F9090C9400000F931F93CF93C5 :100110001C060C94F9090C9400000F931F93CF93C5
:10012000DF938C01EB01009731F46115710519F42F :10012000DF938C01EB01009731F46115710519F42F
:1001300020E030E038C081E090E06EE070E00E94A6 :1001300020E030E038C081E090E06EE070E00E94A6
:10014000CB02FC019C01009771F180E8838320972A :10014000CB02FC019C01009771F180E8838320972A
:1001500071F0D387C28781E883838091E702909111 :1001500071F0D387C28781E883838091E702909111
:10016000E802892B21F4F093E802E093E7020115FD :10016000E802892B21F4F093E802E093E7020115FD
:100170001105C9F011870087838182608383809194 :100170001105C9F011870087838182608383809194
:10018000E9029091EA02892B71F4F093EA02E0937C :10018000E9029091EA02892B71F4F093EA02E0937C
:10019000E9028091EB029091EC02892B21F4F0931B :10019000E9028091EB029091EC02892B21F4F0931B
:1001A000EC02E093EB02C901DF91CF911F910F9117 :1001A000EC02E093EB02C901DF91CF911F910F9117
:1001B0000895A0E0B0E0EFEDF0E00C94CC09FE0172 :1001B0000895A0E0B0E0EFEDF0E00C94CC09FE0172
:1001C0003596619171918091E9029091EA02AF01B7 :1001C0003596619171918091E9029091EA02AF01B7
:1001D0000E94EE002096E2E00C94E809ABE0B0E06B :1001D0000E94EE002096E2E00C94E809ABE0B0E06B
:1001E000E4EFF0E00C94BC093C012B015A01FC0146 :1001E000E4EFF0E00C94BC093C012B015A01FC0146
:1001F00017821682838181FD03C06FEF7FEFC6C136 :1001F00017821682838181FD03C06FEF7FEFC6C136
:100200009AE0892E1E010894211C311CF3012381E0 :100200009AE0892E1E010894211C311CF3012381E0
:10021000F20123FD859123FF81912F01882309F4A9 :10021000F20123FD859123FF81912F01882309F4A9
:10022000B2C1853239F423FD859123FF81912F01DD :10022000B2C1853239F423FD859123FF81912F01DD
:10023000853229F490E0B3010E940604E7CF982F9D :10023000853229F490E0B3010E940604E7CF982F9D
:10024000FF24EE249924FFE1FF15D0F09B3269F0E2 :10024000FF24EE249924FFE1FF15D0F09B3269F0E2
:100250009C3228F4903259F0933291F40EC09D32C2 :100250009C3228F4903259F0933291F40EC09D32C2
:1002600049F0903369F441E024C052E0F52A84E07B :1002600049F0903369F441E024C052E0F52A84E07B
:10027000F82A28C098E0F92A25C0E0E1FE2A22C029 :10027000F82A28C098E0F92A25C0E0E1FE2A22C029
:10028000F7FC29C0892F80538A3070F4F6FE05C030 :10028000F7FC29C0892F80538A3070F4F6FE05C030
:10029000989C902C1124980E15C0E89CE02C1124F9 :10029000989C902C1124980E15C0E89CE02C1124F9
:1002A000E80EF0E2FF2A0EC09E3229F4F6FC6BC184 :1002A000E80EF0E2FF2A0EC09E3229F4F6FC6BC184
:1002B00040E4F42A07C09C3619F450E8F52A02C03D :1002B00040E4F42A07C09C3619F450E8F52A02C03D
:1002C000983649F4F20123FD959123FF91912F0176 :1002C000983649F4F20123FD959123FF91912F0176
:1002D000992309F0B8CF892F8554833018F08052C4 :1002D000992309F0B8CF892F8554833018F08052C4
:1002E000833038F444E050E0A40EB51E5FE3598338 :1002E000833038F444E050E0A40EB51E5FE3598338
:1002F0000FC0933631F0933779F0933509F056C03B :1002F0000FC0933631F0933779F0933509F056C03B
:1003000020C0F5018081898342E050E0A40EB51E33 :1003000020C0F5018081898342E050E0A40EB51E33
:10031000610101E010E012C0F501C080D180F6FC5F :10031000610101E010E012C0F501C080D180F6FC5F
:1003200003C06FEF7FEF02C0692D70E042E050E044 :1003200003C06FEF7FEF02C0692D70E042E050E044
:10033000A40EB51EC6010E94FB038C015FE7F522E7 :10033000A40EB51EC6010E94FB038C015FE7F522E7
:1003400014C0F501C080D180F6FC03C06FEF7FEFD1 :1003400014C0F501C080D180F6FC03C06FEF7FEFD1
:1003500002C0692D70E042E050E0A40EB51EC60157 :1003500002C0692D70E042E050E0A40EB51EC60157
:100360000E94E9038C0150E8F52AF3FE07C01AC089 :100360000E94E9038C0150E8F52AF3FE07C01AC089
:1003700080E290E0B3010E940604EA948E2D90E0A2 :1003700080E290E0B3010E940604EA948E2D90E0A2
:1003800008171907A8F30EC0F601F7FC8591F7FED0 :1003800008171907A8F30EC0F601F7FC8591F7FED0
:1003900081916F0190E0B3010E940604E110EA949C :1003900081916F0190E0B3010E940604E110EA949C
:1003A000015010400115110579F7EAC0943611F09B :1003A000015010400115110579F7EAC0943611F09B
:1003B000993669F5F7FE08C0F50120813181428147 :1003B000993669F5F7FE08C0F50120813181428147
:1003C000538184E090E00AC0F501808191819C0115 :1003C000538184E090E00AC0F501808191819C0115
:1003D000442737FD4095542F82E090E0A80EB91EC7 :1003D000442737FD4095542F82E090E0A80EB91EC7
:1003E0009FE6F92257FF09C0509540953095219519 :1003E0009FE6F92257FF09C0509540953095219519
:1003F0003F4F4F4F5F4FE0E8FE2ACA01B901A1010C :1003F0003F4F4F4F5F4FE0E8FE2ACA01B901A1010C
:100400002AE030E00E943204D82ED21840C095373E :100400002AE030E00E943204D82ED21840C095373E
:1004100029F41F2D1F7E2AE030E01DC01F2D197FFB :1004100029F41F2D1F7E2AE030E01DC01F2D197FFB
:100420009F3661F0903720F4983509F0ACC00FC0CA :100420009F3661F0903720F4983509F0ACC00FC0CA
:10043000903739F0983709F0A6C004C028E030E0C2 :10043000903739F0983709F0A6C004C028E030E0C2
:100440000AC0106114FD146020E130E004C014FD06 :100440000AC0106114FD146020E130E004C014FD06
:10045000166020E132E017FF08C0F501608171816C :10045000166020E132E017FF08C0F501608171816C
:100460008281938144E050E008C0F5018081918150 :100460008281938144E050E008C0F5018081918150
:10047000BC0180E090E042E050E0A40EB51EA10176 :10047000BC0180E090E042E050E0A40EB51EA10176
:100480000E943204D82ED2188FE7F82EF122F6FE01 :100480000E943204D82ED2188FE7F82EF122F6FE01
:100490000BC05EEFF522D91438F4F4FE07C0F2FC6D :100490000BC05EEFF522D91438F4F4FE07C0F2FC6D
:1004A00005C08FEEF82202C01D2D01C0192DF4FEEB :1004A00005C08FEEF82202C01D2D01C0192DF4FEEB
:1004B0000DC0FE01ED0DF11D8081803319F499EE20 :1004B0000DC0FE01ED0DF11D8081803319F499EE20
:1004C000F92208C01F5FF2FE05C003C08F2D867899 :1004C000F92208C01F5FF2FE05C003C08F2D867899
:1004D00009F01F5F0F2DF3FC14C0F0FE0FC01E15B6 :1004D00009F01F5F0F2DF3FC14C0F0FE0FC01E15B6
:1004E00010F09D2C0BC09D2C9E0C911A1E2D06C049 :1004E00010F09D2C0BC09D2C9E0C911A1E2D06C049
:1004F00080E290E0B3010E9406041F5F1E15C0F366 :1004F00080E290E0B3010E9406041F5F1E15C0F366
:1005000004C01E1510F4E11A01C0EE2404FF0FC050 :1005000004C01E1510F4E11A01C0EE2404FF0FC050
:1005100080E390E0B3010E94060402FF1DC001FDCC :1005100080E390E0B3010E94060402FF1DC001FDCC
:1005200003C088E790E00EC088E590E00BC0802F04 :1005200003C088E790E00EC088E590E00BC0802F04
:10053000867891F001FF02C08BE201C080E2F7FCF7 :10053000867891F001FF02C08BE201C080E2F7FCF7
:100540008DE290E0B3010E94060406C080E390E0D3 :100540008DE290E0B3010E94060406C080E390E0D3
:10055000B3010E9406049A94D914C0F3DA94F1010D :10055000B3010E9406049A94D914C0F3DA94F1010D
:10056000ED0DF11D808190E0B3010E940604DD20B5 :10056000ED0DF11D808190E0B3010E940604DD20B5
:10057000A9F706C080E290E0B3010E940604EA9465 :10057000A9F706C080E290E0B3010E940604EA9465
:10058000EE20C1F743CEF30166817781CB012B9634 :10058000EE20C1F743CEF30166817781CB012B9634
:10059000E2E10C94D8090F931F93CF93DF93689FE8 :10059000E2E10C94D8090F931F93CF93DF93689FE8
:1005A0008001699F100D789F100D1124C8010E94D1 :1005A0008001699F100D789F100D1124C8010E94D1
:1005B000E702EC01009729F060E070E0A8010E94DA :1005B000E702EC01009729F060E070E0A8010E94DA
:1005C000F403CE01DF91CF911F910F910895CF9346 :1005C000F403CE01DF91CF911F910F910895CF9346
:1005D000DF93BC018230910510F462E070E0A091DD :1005D000DF93BC018230910510F462E070E0A091DD
:1005E000EF02B091F002ED01E0E0F0E040E050E019 :1005E000EF02B091F002ED01E0E0F0E040E050E019
:1005F00021C0888199818617970769F48A819B8138 :1005F00021C0888199818617970769F48A819B8138
:10060000309719F09383828304C09093F002809313 :10060000309719F09383828304C09093F002809313
:10061000EF02FE0134C06817790738F4411551051F :10061000EF02FE0134C06817790738F4411551051F
:1006200019F08417950708F4AC01FE018A819B81BB :1006200019F08417950708F4AC01FE018A819B81BB
:100630009C01E9012097E9F641155105A9F1CA018C :100630009C01E9012097E9F641155105A9F1CA018C
:10064000861B970B049708F4BA01E0E0F0E02AC09B :10064000861B970B049708F4BA01E0E0F0E02AC09B
:100650008D919C91119784179507F9F4641775078C :100650008D919C91119784179507F9F4641775078C
:1006600081F412968D919C911397309719F0938392 :1006600081F412968D919C911397309719F0938392
:10067000828304C09093F0028093EF02FD013296D2 :10067000828304C09093F0028093EF02FD013296D2
:100680004CC0CA01861B970BFD01E80FF91F61934F :100680004CC0CA01861B970BFD01E80FF91F61934F
:10069000719302978D939C9340C0FD018281938159 :10069000719302978D939C9340C0FD018281938159
:1006A0009C01D9011097A1F68091ED029091EE0284 :1006A0009C01D9011097A1F68091ED029091EE0284
:1006B000892B41F480912301909124019093EE02C3 :1006B000892B41F480912301909124019093EE02C3
:1006C0008093ED024091250150912601411551057D :1006C0008093ED024091250150912601411551057D
:1006D00041F44DB75EB78091210190912201481BF2 :1006D00041F44DB75EB78091210190912201481BF2
:1006E000590B2091ED023091EE02CA01821B930B4F :1006E000590B2091ED023091EE02CA01821B930B4F
:1006F0008617970780F0AB014E5F5F4F8417950711 :1006F0008617970780F0AB014E5F5F4F8417950711
:1007000050F0420F531F5093EE024093ED02F90157 :1007000050F0420F531F5093EE024093ED02F90157
:100710006193719302C0E0E0F0E0CF01DF91CF91EF :100710006193719302C0E0E0F0E0CF01DF91CF91EF
:100720000895CF93DF93009709F450C0EC0122970E :100720000895CF93DF93009709F450C0EC0122970E
:100730001B821A82A091EF02B091F002109709F18A :100730001B821A82A091EF02B091F002109709F18A
:1007400040E050E0AC17BD0708F1BB83AA83FE016F :1007400040E050E0AC17BD0708F1BB83AA83FE016F
:1007500021913191E20FF31FAE17BF0779F48D910C :1007500021913191E20FF31FAE17BF0779F48D910C
:100760009C911197280F391F2E5F3F4F39832883A3 :100760009C911197280F391F2E5F3F4F39832883A3
:1007700012968D919C9113979B838A834115510505 :1007700012968D919C9113979B838A834115510505
:1007800071F4D093F002C093EF0220C012968D91C5 :1007800071F4D093F002C093EF0220C012968D91C5
:100790009C911397AD01009711F0DC01D3CFFA01C2 :100790009C911397AD01009711F0DC01D3CFFA01C2
:1007A000D383C28321913191E20FF31FCE17DF076C :1007A000D383C28321913191E20FF31FCE17DF076C
:1007B00069F488819981280F391F2E5F3F4FFA0114 :1007B00069F488819981280F391F2E5F3F4FFA0114
:1007C000318320838A819B8193838283DF91CF91C0 :1007C000318320838A819B8193838283DF91CF91C0
:1007D0000895FC010590615070400110D8F7809594 :1007D0000895FC010590615070400110D8F7809594
:1007E00090958E0F9F1F0895DC0101C06D934150BD :1007E00090958E0F9F1F0895DC0101C06D934150BD
:1007F0005040E0F70895FC016150704001900110F5 :1007F0005040E0F70895FC016150704001900110F5
:10080000D8F7809590958E0F9F1F08950F931F9393 :10080000D8F7809590958E0F9F1F08950F931F9393
:10081000CF93DF938C01EB018B8181FF1BC082FFA3 :10081000CF93DF938C01EB018B8181FF1BC082FFA3
:100820000DC02E813F818C819D812817390764F48A :100820000DC02E813F818C819D812817390764F48A
:10083000E881F9810193F983E88306C0E885F985A9 :10083000E881F9810193F983E88306C0E885F985A9
:10084000802F0995892B31F48E819F8101969F839A :10084000802F0995892B31F48E819F8101969F839A
:100850008E8302C00FEF1FEFC801DF91CF911F9170 :100850008E8302C00FEF1FEFC801DF91CF911F9170
:100860000F910895FA01AA27283051F1203181F122 :100860000F910895FA01AA27283051F1203181F122
:10087000E8946F936E7F6E5F7F4F8F4F9F4FAF4FA8 :10087000E8946F936E7F6E5F7F4F8F4F9F4FAF4FA8
:10088000B1E03ED0B4E03CD0670F781F891F9A1FBB :10088000B1E03ED0B4E03CD0670F781F891F9A1FBB
:10089000A11D680F791F8A1F911DA11D6A0F711D6F :10089000A11D680F791F8A1F911DA11D6A0F711D6F
:1008A000811D911DA11D20D009F468943F912AE07B :1008A000811D911DA11D20D009F468943F912AE07B
:1008B000269F11243019305D3193DEF6CF01089563 :1008B000269F11243019305D3193DEF6CF01089563
:1008C000462F4770405D4193B3E00FD0C9F7F6CF94 :1008C000462F4770405D4193B3E00FD0C9F7F6CF94
:1008D000462F4F70405D4A3318F0495D31FD40525C :1008D000462F4F70405D4A3318F0495D31FD40525C
:1008E000419302D0A9F7EACFB4E0A69597958795F2 :1008E000419302D0A9F7EACFB4E0A69597958795F2
:1008F00077956795BA95C9F70097610571050895D1 :1008F00077956795BA95C9F70097610571050895D1
:100900009B01AC010A2E069457954795379527957C :100900009B01AC010A2E069457954795379527957C
:10091000BA95C9F7620F731F841F951FA01D089514 :10091000BA95C9F7620F731F841F951FA01D089514
:100920008AE391E068E049E00E9475070895FF922C :100920008AE391E068E049E00E9475070895FF922C
:100930000F931F93CF93DF9380E8E7E4F1E0DF01AB :100930000F931F93CF93DF9380E8E7E4F1E0DF01AB
:100940001D928A95E9F704E610E021C08AE391E060 :100940001D928A95E9F704E610E021C08AE391E060
:100950006F2D0E94F2078AE391E00E94840880E8EC :100950006F2D0E94F2078AE391E00E94840880E8EC
:1009600090E00E94D7058AE391E00E947C078AE329 :1009600090E00E94D7058AE391E00E947C078AE329
:1009700091E00E944608882329F088819981019698 :1009700091E00E944608882329F088819981019698
:10098000998388832297FA94BFEFFB16F9F60150FA :10098000998388832297FA94BFEFFB16F9F60150FA
:100990001040EFEF0F3F1E0729F0C5E4D2E08FE7CC :100990001040EFEF0F3F1E0729F0C5E4D2E08FE7CC
:1009A000F82ED4CFC7E4D1E000E011E000D000D0B1 :1009A000F82ED4CFC7E4D1E000E011E000D000D0B1
:1009B000ADB7BEB712961C930E931197899199917A :1009B000ADB7BEB712961C930E931197899199917A
:1009C0008F70907014969C938E9313970E94D90009 :1009C0008F70907014969C938E9313970E94D90009
:1009D0000F900F900F900F90B2E0C734DB0731F704 :1009D0000F900F900F900F90B2E0C734DB0731F704
:1009E00000D083E091E0EDB7FEB7928381830E944F :1009E00000D083E091E0EDB7FEB7928381830E944F
:1009F000D9000F900F90DF91CF911F910F91FF9031 :1009F000D9000F900F90DF91CF911F910F91FF9031
:100A0000089580E895E060E070E00E948D00089510 :100A0000089580E895E060E070E00E948D00089510
:100A10000F931F93CF93DF9384ED92E040E051EE6C :100A10000F931F93CF93DF9384ED92E040E051EE6C
:100A200060E070E00E9454060E94010500D086E05C :100A200060E070E00E9454060E94010500D086E05C
:100A300091E0EDB7FEB7928381830E94D9000F90B9 :100A300091E0EDB7FEB7928381830E94D9000F90B9
:100A40000F908AE391E00E944B088AE391E060E016 :100A40000F908AE391E00E944B088AE391E060E016
:100A50000E94E8078AE391E00E9484088AE391E01B :100A50000E94E8078AE391E00E9484088AE391E01B
:100A60000E947C07C0E0D0E000E011E000D000D0A0 :100A60000E947C07C0E0D0E000E011E000D000D0A0
:100A7000EDB7FEB712830183CE0124E095958795EB :100A7000EDB7FEB712830183CE0124E095958795EB
:100A80002A95E1F7948383830E94D90021960F90E1 :100A80002A95E1F7948383830E94D90021960F90E1
:100A90000F900F900F90C038D10541F700D083E040 :100A90000F900F900F90C038D10541F700D083E040
:100AA00091E0EDB7FEB7928381830E94D900C0E048 :100AA00091E0EDB7FEB7928381830E94D900C0E048
:100AB000D0E00F900F9000D000D0EDB7FEB70183CB :100AB000D0E00F900F9000D000D0EDB7FEB70183CB
:100AC0001283CE018F709070948383830E94D9002B :100AC0001283CE018F709070948383830E94D9002B
:100AD00021960F900F900F900F90C038D10559F7C5 :100AD00021960F900F900F900F90C038D10559F7C5
:100AE00000D083E091E0EDB7FEB7928381830E944E :100AE00000D083E091E0EDB7FEB7928381830E944E
:100AF000D9000F900F90DF91CF911F910F91089522 :100AF000D9000F900F90DF91CF911F910F91089522
:100B00000F931F93082F84ED92E0602F0E94280717 :100B00000F931F93082F84ED92E0602F0E94280717
:100B1000112707FD1095C8011F910F9108951F928D :100B1000112707FD1095C8011F910F9108951F928D
:100B20000F920FB60F9211242F933F938F939F93A1 :100B20000F920FB60F9211242F933F938F939F93A1
:100B3000AF93BF9380914B0290914C02A0914D02D4 :100B3000AF93BF9380914B0290914C02A0914D02D4
:100B4000B0914E0230914F020196A11DB11D232F8D :100B4000B0914E0230914F020196A11DB11D232F8D
:100B50002D5F2D3720F02D570196A11DB11D20933B :100B50002D5F2D3720F02D570196A11DB11D20933B
:100B60004F0280934B0290934C02A0934D02B0939E :100B60004F0280934B0290934C02A0934D02B0939E
:100B70004E028091470290914802A0914902B091A3 :100B70004E028091470290914802A0914902B091A3
:100B80004A020196A11DB11D80934702909348022D :100B80004A020196A11DB11D80934702909348022D
:100B9000A0934902B0934A02BF91AF919F918F9168 :100B9000A0934902B0934A02BF91AF919F918F9168
:100BA0003F912F910F900FBE0F901F9018950197B6 :100BA0003F912F910F900FBE0F901F9018950197B6
:100BB00039F0880F991F880F991F02970197F1F755 :100BB00039F0880F991F880F991F02970197F1F755
:100BC0000895789484B5826084BD84B5816084BDC5 :100BC0000895789484B5826084BD84B5816084BDC5
:100BD00085B5826085BD85B5816085BDEEE6F0E0B6 :100BD00085B5826085BD85B5816085BDEEE6F0E0B6
:100BE000808181608083E1E8F0E010828081826012 :100BE000808181608083E1E8F0E010828081826012
:100BF0008083808181608083E0E8F0E08081816093 :100BF0008083808181608083E0E8F0E08081816093
:100C00008083E1EBF0E0808184608083E0EBF0E0C2 :100C00008083E1EBF0E0808184608083E0EBF0E0C2
:100C1000808181608083EAE7F0E080818460808366 :100C1000808181608083EAE7F0E080818460808366
:100C20008081826080838081816080838081806810 :100C20008081826080838081816080838081806810
:100C300080831092C10008950E94E1050E9408057A :100C300080831092C10008950E94E1050E9408057A
:100C40000E949704FDCF1F920F920FB60F921124AE :100C40000E949704FDCF1F920F920FB60F921124AE
:100C50002F933F934F938F939F93EF93FF934091E5 :100C50002F933F934F938F939F93EF93FF934091E5
:100C6000C600E091D002F091D10231969F012F771A :100C6000C600E091D002F091D10231969F012F771A
:100C7000307031978091D2029091D30228173907B2 :100C7000307031978091D2029091D30228173907B2
:100C800039F0E05BFD4F40833093D1022093D002D6 :100C800039F0E05BFD4F40833093D1022093D002D6
:100C9000FF91EF919F918F914F913F912F910F90E5 :100C9000FF91EF919F918F914F913F912F910F90E5
:100CA0000FBE0F901F901895AF92BF92DF92EF92F8 :100CA0000FBE0F901F901895AF92BF92DF92EF92F8
:100CB000FF920F931F93CF93DF93EC017A018B0187 :100CB000FF920F931F93CF93DF93EC017A018B0187
:100CC000DD24403081EE580780E0680780E0780737 :100CC000DD24403081EE580780E0680780E0780737
:100CD00011F0DD24D39491E0A92EB12CE885F9859B :100CD00011F0DD24D39491E0A92EB12CE885F9859B
:100CE000DD2069F0C5010A8802C0880F991F0A94A7 :100CE000DD2069F0C5010A8802C0880F991F0A94A7
:100CF000E2F7808360E079E08DE390E005C0108248 :100CF000E2F7808360E079E08DE390E005C0108248
:100D000060E874E88EE190E0A80197010E949A09DA :100D000060E874E88EE190E0A80197010E949A09DA
:100D10002150304040405040569547953795279593 :100D10002150304040405040569547953795279593
:100D200080E12030380720F0DD2011F0DD24D6CF1F :100D200080E12030380720F0DD2011F0DD24D6CF1F
:100D3000EC81FD813083EE81FF812083EA85FB8594 :100D3000EC81FD813083EE81FF812083EA85FB8594
:100D4000208141E050E0CA010E8402C0880F991F43 :100D4000208141E050E0CA010E8402C0880F991F43
:100D50000A94E2F7282B2083EA85FB852081CA01CB :100D50000A94E2F7282B2083EA85FB852081CA01CB
:100D60000F8402C0880F991F0A94E2F7282B208372 :100D60000F8402C0880F991F0A94E2F7282B208372
:100D7000EA85FB858081088802C0440F551F0A94CC :100D7000EA85FB858081088802C0440F551F0A94CC
:100D8000E2F7842B8083DF91CF911F910F91FF9029 :100D8000E2F7842B8083DF91CF911F910F91FF9029
:100D9000EF90DF90BF90AF900895DC011296ED9137 :100D9000EF90DF90BF90AF900895DC011296ED9137
:100DA000FC911397E058FF4F2191319180819181FF :100DA000FC911397E058FF4F2191319180819181FF
:100DB000281B390B2F773070C9010895DC0112967A :100DB000281B390B2F773070C9010895DC0112967A
:100DC000ED91FC911397EE57FF4F20813181929165 :100DC000ED91FC911397EE57FF4F20813181929165
:100DD0008291E058F0408217930719F42FEF3FEF0C :100DD0008291E058F0408217930719F42FEF3FEF0C
:100DE00005C0E20FF31F8081282F30E0C90108956C :100DE00005C0E20FF31F8081282F30E0C90108956C
:100DF000DC011296ED91FC911397DF01AE57BF4FC6 :100DF000DC011296ED91FC911397DF01AE57BF4FC6
:100E00002D913C911197E058FF4F80819181E058DE :100E00002D913C911197E058FF4F80819181E058DE
:100E1000F0408217930719F42FEF3FEF0BC0E20F5A :100E1000F0408217930719F42FEF3FEF0BC0E20F5A
:100E2000F31F80812F5F3F4F2F7730702D933C93BE :100E2000F31F80812F5F3F4F2F7730702D933C93BE
:100E3000282F30E0C9010895DC011296ED91FC9154 :100E3000282F30E0C9010895DC011296ED91FC9154
:100E40001397EE57FF4F808191819293829308957B :100E40001397EE57FF4F808191819293829308957B
:100E5000FC01A085B18521898C9190E0022E02C011 :100E5000FC01A085B18521898C9190E0022E02C011
:100E6000959587950A94E2F780FFF6CF0484F5857F :100E6000959587950A94E2F780FFF6CF0484F5857F
:100E7000E02D608308958BE291E09093D5028093FA :100E7000E02D608308958BE291E09093D5028093FA
:100E8000D40280E592E09093D7028093D60285EC5D :100E8000D40280E592E09093D7028093D60285EC5D
:100E900090E09093D9028093D80284EC90E09093F4 :100E900090E09093D9028093D80284EC90E09093F4
:100EA000DB028093DA0280EC90E09093DD02809385 :100EA000DB028093DA0280EC90E09093DD02809385
:100EB000DC0281EC90E09093DF028093DE0286EC0E :100EB000DC0281EC90E09093DF028093DE0286EC0E
:100EC00090E09093E1028093E00284E08093E2025C :100EC00090E09093E1028093E00284E08093E2025C
:100ED00083E08093E30287E08093E40285E08093DF :100ED00083E08093E30287E08093E40285E08093DF
:100EE000E50281E08093E6020895FC01608341837E :100EE000E50281E08093E6020895FC01608341837E
:100EF00080E2828313820895FC01808160E00E9479 :100EF00080E2828313820895FC01808160E00E9479
:100F0000CD080895FF920F931F938C01F62E80E079 :100F0000CD080895FF920F931F938C01F62E80E079
:100F10000E94650985E00E946A09F80181816F2DB0 :100F10000E94650985E00E946A09F80181816F2DB0
:100F20000E94CD081F910F91FF9008951F93CF93BA :100F20000E94CD081F910F91FF9008951F93CF93BA
:100F3000DF93EC0160E070E00E94820781EE8EBDDD :100F3000DF93EC0160E070E00E94820781EE8EBDDD
:100F40000DB407FEFDCF1EB5CE0161E070E00E943A :100F40000DB407FEFDCF1EB5CE0161E070E00E943A
:100F50008207812FDF91CF911F9108951F93CF9327 :100F50008207812FDF91CF911F9108951F93CF9327
:100F6000DF93EC0160E070E00E94820782EE8EBDAC :100F6000DF93EC0160E070E00E94820782EE8EBDAC
:100F70000DB407FEFDCF1EB5CE0161E070E00E940A :100F70000DB407FEFDCF1EB5CE0161E070E00E940A
:100F80008207812FDF91CF911F9108950F931F93B7 :100F80008207812FDF91CF911F9108950F931F93B7
:100F9000CF93DF93EC01162F042F60E070E00E94E6 :100F9000CF93DF93EC01162F042F60E070E00E94E6
:100FA00082071F7110621EBD0DB407FEFDCF1EB576 :100FA00082071F7110621EBD0DB407FEFDCF1EB576
:100FB0000EBD0DB407FEFDCF8EB5CE0161E070E031 :100FB0000EBD0DB407FEFDCF8EB5CE0161E070E031
:100FC0000E948207812FDF91CF911F910F91089589 :100FC0000E948207812FDF91CF911F910F91089589
:100FD000662319F061E04FE302C061E040E00E9447 :100FD000662319F061E04FE302C061E040E00E9447
:100FE000C6070895462F603808F04FE765E00E9475 :100FE000C6070895462F603808F04FE765E00E9475
:100FF000C6070895EF92FF920F931F93CF93DF934D :100FF000C6070895EF92FF920F931F93CF93DF934D
:101000007C01162FEA01022F60E070E00E94820747 :101000007C01162FEA01022F60E070E00E94820747
:101010001F7110621EBD0DB407FEFDCF1EB508C0C6 :101010001F7110621EBD0DB407FEFDCF1EB508C0C6
:1010200088818EBD0DB407FEFDCF21968EB501508F :1010200088818EBD0DB407FEFDCF21968EB501508F
:101030000023B1F7C70161E070E00E948207812FB1 :101030000023B1F7C70161E070E00E948207812FB1
:10104000DF91CF911F910F91FF90EF9008951F9323 :10104000DF91CF911F910F91FF90EF9008951F9323
:10105000CF93DF93EC01162F60E070E00E948207CF :10105000CF93DF93EC01162F60E070E00E948207CF
:101060001F711EBD0DB407FEFDCF8EB58FEF8EBD77 :101060001F711EBD0DB407FEFDCF8EB58FEF8EBD77
:101070000DB407FEFDCF1EB5CE0161E070E00E9409 :101070000DB407FEFDCF1EB5CE0161E070E00E9409
:101080008207812FDF91CF911F91089569E00E941F :101080008207812FDF91CF911F91089569E00E941F
:101090002708817008950F931F938C01FC018081B4 :101090002708817008950F931F938C01FC018081B4
:1010A00061E00E94A708F801818161E00E94A70821 :1010A00061E00E94A708F801818161E00E94A70821
:1010B000F801808160E00E94CD08C80161E070E025 :1010B000F801808160E00E94CD08C80161E070E025
:1010C0000E9482070E947B0981E00E945C0980E007 :1010C0000E9482070E947B0981E00E945C0980E007
:1010D0000E94650985E00E946A09C80164E04FEF3B :1010D0000E94650985E00E946A09C80164E04FEF3B
:1010E0000E94C607C80167E040E70E94C607C80122 :1010E0000E94C607C80167E040E70E94C607C80122
:1010F0000E94AE07C8010E949607C80161E00E94E5 :1010F0000E94AE07C8010E949607C80161E00E94E5
:10110000F2071F910F9108950F931F938C0160E0D8 :10110000F2071F910F9108950F931F938C0160E0D8
:101110004BE00E94C607C80167E040E70E94C6078F :101110004BE00E94C607C80167E040E70E94C6078F
:10112000A8014B5F5F4FC8016AE025E00E94FA0703 :10112000A8014B5F5F4FC8016AE025E00E94FA0703
:10113000C8010E94AE07F801808161E00E94CD08DD :10113000C8010E94AE07F801808161E00E94CD08DD
:1011400082E890E00E94D7051F910F910895482FE3 :1011400082E890E00E94D7051F910F910895482FE3
:1011500050E0CA0186569F4FFC0124914A575F4FC9 :1011500050E0CA0186569F4FFC0124914A575F4FC9
:10116000FA0184918823C1F0E82FF0E0EE0FFF1F11 :10116000FA0184918823C1F0E82FF0E0EE0FFF1F11
:10117000E859FF4FA591B491662341F49FB7F894C5 :10117000E859FF4FA591B491662341F49FB7F894C5
:101180008C91209582238C939FBF08959FB7F894EC :101180008C91209582238C939FBF08959FB7F894EC
:101190008C91822B8C939FBF0895482F50E0CA01F9 :101190008C91822B8C939FBF0895482F50E0CA01F9
:1011A00082559F4FFC012491CA0186569F4FFC0136 :1011A00082559F4FFC012491CA0186569F4FFC0136
:1011B00034914A575F4FFA019491992309F444C03E :1011B00034914A575F4FFA019491992309F444C03E
:1011C000222351F1233071F0243028F42130A1F092 :1011C000222351F1233071F0243028F42130A1F092
:1011D000223011F514C02630B1F02730C1F0243090 :1011D000223011F514C02630B1F02730C1F0243090
:1011E000D9F404C0809180008F7703C08091800083 :1011E000D9F404C0809180008F7703C08091800083
:1011F0008F7D8093800010C084B58F7702C084B546 :1011F0008F7D8093800010C084B58F7702C084B546
:101200008F7D84BD09C08091B0008F7703C080912D :101200008F7D84BD09C08091B0008F7703C080912D
:10121000B0008F7D8093B000E92FF0E0EE0FFF1F4C :10121000B0008F7D8093B000E92FF0E0EE0FFF1F4C
:10122000EE58FF4FA591B491662341F49FB7F8940F :10122000EE58FF4FA591B491662341F49FB7F8940F
:101230008C91309583238C939FBF08959FB7F8942A :101230008C91309583238C939FBF08959FB7F8942A
:101240008C91832B8C939FBF08950F931F93CF9303 :101240008C91832B8C939FBF08950F931F93CF9303
:10125000DF938C01EB0109C02196D801ED91FC913F :10125000DF938C01EB0109C02196D801ED91FC913F
:101260000190F081E02DC801099568816623A1F7FE :101260000190F081E02DC801099568816623A1F7FE
:10127000DF91CF911F910F910895EF92FF920F93FD :10127000DF91CF911F910F910895EF92FF920F93FD
:101280001F93CF93DF938C017B01EA010CC0D70140 :101280001F93CF93DF938C017B01EA010CC0D70140
:101290006D917D01D801ED91FC910190F081E02DDF :101290006D917D01D801ED91FC910190F081E02DDF
:1012A000C80109952197209791F7DF91CF911F9160 :1012A000C80109952197209791F7DF91CF911F9160
:1012B0000F91FF90EF900895882319F48CB5806208 :1012B0000F91FF90EF900895882319F48CB5806208
:1012C00002C08CB58F7D8CBD08959CB5937F982B03 :1012C00002C08CB58F7D8CBD08959CB5937F982B03
:1012D0009CBD08952CB5382F33702C7F322B3CBD2C :1012D0009CBD08952CB5382F33702C7F322B3CBD2C
:1012E0002DB590E0959587959595879581702E7F82 :1012E0002DB590E0959587959595879581702E7F82
:1012F000822B8DBD08958DE061E00E94A7088BE0F0 :1012F000822B8DBD08958DE061E00E94A7088BE0F0
:1013000061E00E94A7088AE061E00E94A7088DE0E2 :1013000061E00E94A7088AE061E00E94A7088DE0E2
:1013100060E00E94CD088BE060E00E94CD088AE08A :1013100060E00E94CD088BE060E00E94CD088AE08A
:1013200061E00E94CD088CB580618CBD8CB5806475 :1013200061E00E94CD088CB580618CBD8CB5806475
:101330008CBD0895A1E21A2EAA1BBB1BFD010DC096 :101330008CBD0895A1E21A2EAA1BBB1BFD010DC096
:10134000AA1FBB1FEE1FFF1FA217B307E407F50775 :10134000AA1FBB1FEE1FFF1FA217B307E407F50775
:1013500020F0A21BB30BE40BF50B661F771F881F51 :1013500020F0A21BB30BE40BF50B661F771F881F51
:10136000991F1A9469F760957095809590959B01E7 :10136000991F1A9469F760957095809590959B01E7
:10137000AC01BD01CF0108952F923F924F925F9231 :10137000AC01BD01CF0108952F923F924F925F9231
:101380006F927F928F929F92AF92BF92CF92DF9295 :101380006F927F928F929F92AF92BF92CF92DF9295
:10139000EF92FF920F931F93CF93DF93CDB7DEB7FA :10139000EF92FF920F931F93CF93DF93CDB7DEB7FA
:1013A000CA1BDB0B0FB6F894DEBF0FBECDBF09948E :1013A000CA1BDB0B0FB6F894DEBF0FBECDBF09948E
:1013B0002A88398848885F846E847D848C849B84E5 :1013B0002A88398848885F846E847D848C849B84E5
:1013C000AA84B984C884DF80EE80FD800C811B81F3 :1013C000AA84B984C884DF80EE80FD800C811B81F3
:1013D000AA81B981CE0FD11D0FB6F894DEBF0FBE22 :1013D000AA81B981CE0FD11D0FB6F894DEBF0FBE22
:1013E000CDBFED010895EE0FFF1F0590F491E02DA4 :1013E000CDBFED010895EE0FFF1F0590F491E02DA4
:0613F0000994F894FFCF00 :0613F0000994F894FFCF00
:1013F6002578000A0D000A0D524632342F657861B1 :1013F6002578000A0D000A0D524632342F657861B1
:101406006D706C65732F7363616E6E65722F0A0D56 :101406006D706C65732F7363616E6E65722F0A0D56
:10141600002000F102000000000000280725093D19 :10141600002000F102000000000000280725093D19
:0A14260009CD06F806DE061C0700DB :0A14260009CD06F806DE061C0700DB
:00000001FF :00000001FF
+651 -651
View File
File diff suppressed because it is too large Load Diff
+194 -194
View File
@@ -1,194 +1,194 @@
#ifndef UART_H #ifndef UART_H
#define UART_H #define UART_H
/************************************************************************ /************************************************************************
Title: Interrupt UART library with receive/transmit circular buffers Title: Interrupt UART library with receive/transmit circular buffers
Author: Peter Fleury <pfleury@gmx.ch> http://jump.to/fleury Author: Peter Fleury <pfleury@gmx.ch> http://jump.to/fleury
File: $Id: uart.h,v 1.8.2.1 2007/07/01 11:14:38 peter Exp $ File: $Id: uart.h,v 1.8.2.1 2007/07/01 11:14:38 peter Exp $
Software: AVR-GCC 4.1, AVR Libc 1.4 Software: AVR-GCC 4.1, AVR Libc 1.4
Hardware: any AVR with built-in UART, tested on AT90S8515 & ATmega8 at 4 Mhz Hardware: any AVR with built-in UART, tested on AT90S8515 & ATmega8 at 4 Mhz
License: GNU General Public License License: GNU General Public License
Usage: see Doxygen manual Usage: see Doxygen manual
LICENSE: LICENSE:
Copyright (C) 2006 Peter Fleury Copyright (C) 2006 Peter Fleury
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or the Free Software Foundation; either version 2 of the License, or
any later version. any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
************************************************************************/ ************************************************************************/
/** /**
* @defgroup pfleury_uart UART Library * @defgroup pfleury_uart UART Library
* @code #include <uart.h> @endcode * @code #include <uart.h> @endcode
* *
* @brief Interrupt UART library using the built-in UART with transmit and receive circular buffers. * @brief Interrupt UART library using the built-in UART with transmit and receive circular buffers.
* *
* This library can be used to transmit and receive data through the built in UART. * This library can be used to transmit and receive data through the built in UART.
* *
* An interrupt is generated when the UART has finished transmitting or * An interrupt is generated when the UART has finished transmitting or
* receiving a byte. The interrupt handling routines use circular buffers * receiving a byte. The interrupt handling routines use circular buffers
* for buffering received and transmitted data. * for buffering received and transmitted data.
* *
* The UART_RX_BUFFER_SIZE and UART_TX_BUFFER_SIZE constants define * The UART_RX_BUFFER_SIZE and UART_TX_BUFFER_SIZE constants define
* the size of the circular buffers in bytes. Note that these constants must be a power of 2. * the size of the circular buffers in bytes. Note that these constants must be a power of 2.
* You may need to adapt this constants to your target and your application by adding * You may need to adapt this constants to your target and your application by adding
* CDEFS += -DUART_RX_BUFFER_SIZE=nn -DUART_RX_BUFFER_SIZE=nn to your Makefile. * CDEFS += -DUART_RX_BUFFER_SIZE=nn -DUART_RX_BUFFER_SIZE=nn to your Makefile.
* *
* @note Based on Atmel Application Note AVR306 * @note Based on Atmel Application Note AVR306
* @author Peter Fleury pfleury@gmx.ch http://jump.to/fleury * @author Peter Fleury pfleury@gmx.ch http://jump.to/fleury
*/ */
/**@{*/ /**@{*/
#if (__GNUC__ * 100 + __GNUC_MINOR__) < 304 #if (__GNUC__ * 100 + __GNUC_MINOR__) < 304
#error "This library requires AVR-GCC 3.4 or later, update to newer AVR-GCC compiler !" #error "This library requires AVR-GCC 3.4 or later, update to newer AVR-GCC compiler !"
#endif #endif
/* /*
** constants and macros ** constants and macros
*/ */
/** @brief UART Baudrate Expression /** @brief UART Baudrate Expression
* @param xtalcpu system clock in Mhz, e.g. 4000000L for 4Mhz * @param xtalcpu system clock in Mhz, e.g. 4000000L for 4Mhz
* @param baudrate baudrate in bps, e.g. 1200, 2400, 9600 * @param baudrate baudrate in bps, e.g. 1200, 2400, 9600
*/ */
#define UART_BAUD_SELECT(baudRate,xtalCpu) ((xtalCpu)/((baudRate)*16l)-1) #define UART_BAUD_SELECT(baudRate,xtalCpu) ((xtalCpu)/((baudRate)*16l)-1)
/** @brief UART Baudrate Expression for ATmega double speed mode /** @brief UART Baudrate Expression for ATmega double speed mode
* @param xtalcpu system clock in Mhz, e.g. 4000000L for 4Mhz * @param xtalcpu system clock in Mhz, e.g. 4000000L for 4Mhz
* @param baudrate baudrate in bps, e.g. 1200, 2400, 9600 * @param baudrate baudrate in bps, e.g. 1200, 2400, 9600
*/ */
#define UART_BAUD_SELECT_DOUBLE_SPEED(baudRate,xtalCpu) (((xtalCpu)/((baudRate)*8l)-1)|0x8000) #define UART_BAUD_SELECT_DOUBLE_SPEED(baudRate,xtalCpu) (((xtalCpu)/((baudRate)*8l)-1)|0x8000)
/** Size of the circular receive buffer, must be power of 2 */ /** Size of the circular receive buffer, must be power of 2 */
#ifndef UART_RX_BUFFER_SIZE #ifndef UART_RX_BUFFER_SIZE
#define UART_RX_BUFFER_SIZE 32 #define UART_RX_BUFFER_SIZE 32
#endif #endif
/** Size of the circular transmit buffer, must be power of 2 */ /** Size of the circular transmit buffer, must be power of 2 */
#ifndef UART_TX_BUFFER_SIZE #ifndef UART_TX_BUFFER_SIZE
#define UART_TX_BUFFER_SIZE 32 #define UART_TX_BUFFER_SIZE 32
#endif #endif
/* test if the size of the circular buffers fits into SRAM */ /* test if the size of the circular buffers fits into SRAM */
#if ( (UART_RX_BUFFER_SIZE+UART_TX_BUFFER_SIZE) >= (RAMEND-0x60 ) ) #if ( (UART_RX_BUFFER_SIZE+UART_TX_BUFFER_SIZE) >= (RAMEND-0x60 ) )
#error "size of UART_RX_BUFFER_SIZE + UART_TX_BUFFER_SIZE larger than size of SRAM" #error "size of UART_RX_BUFFER_SIZE + UART_TX_BUFFER_SIZE larger than size of SRAM"
#endif #endif
/* /*
** high byte error return code of uart_getc() ** high byte error return code of uart_getc()
*/ */
#define UART_FRAME_ERROR 0x0800 /* Framing Error by UART */ #define UART_FRAME_ERROR 0x0800 /* Framing Error by UART */
#define UART_OVERRUN_ERROR 0x0400 /* Overrun condition by UART */ #define UART_OVERRUN_ERROR 0x0400 /* Overrun condition by UART */
#define UART_BUFFER_OVERFLOW 0x0200 /* receive ringbuffer overflow */ #define UART_BUFFER_OVERFLOW 0x0200 /* receive ringbuffer overflow */
#define UART_NO_DATA 0x0100 /* no receive data available */ #define UART_NO_DATA 0x0100 /* no receive data available */
/* /*
** function prototypes ** function prototypes
*/ */
/** /**
@brief Initialize UART and set baudrate @brief Initialize UART and set baudrate
@param baudrate Specify baudrate using macro UART_BAUD_SELECT() @param baudrate Specify baudrate using macro UART_BAUD_SELECT()
@return none @return none
*/ */
extern void uart_init(unsigned int baudrate); extern void uart_init(unsigned int baudrate);
/** /**
* @brief Get received byte from ringbuffer * @brief Get received byte from ringbuffer
* *
* Returns in the lower byte the received character and in the * Returns in the lower byte the received character and in the
* higher byte the last receive error. * higher byte the last receive error.
* UART_NO_DATA is returned when no data is available. * UART_NO_DATA is returned when no data is available.
* *
* @param void * @param void
* @return lower byte: received byte from ringbuffer * @return lower byte: received byte from ringbuffer
* @return higher byte: last receive status * @return higher byte: last receive status
* - \b 0 successfully received data from UART * - \b 0 successfully received data from UART
* - \b UART_NO_DATA * - \b UART_NO_DATA
* <br>no receive data available * <br>no receive data available
* - \b UART_BUFFER_OVERFLOW * - \b UART_BUFFER_OVERFLOW
* <br>Receive ringbuffer overflow. * <br>Receive ringbuffer overflow.
* We are not reading the receive buffer fast enough, * We are not reading the receive buffer fast enough,
* one or more received character have been dropped * one or more received character have been dropped
* - \b UART_OVERRUN_ERROR * - \b UART_OVERRUN_ERROR
* <br>Overrun condition by UART. * <br>Overrun condition by UART.
* A character already present in the UART UDR register was * A character already present in the UART UDR register was
* not read by the interrupt handler before the next character arrived, * not read by the interrupt handler before the next character arrived,
* one or more received characters have been dropped. * one or more received characters have been dropped.
* - \b UART_FRAME_ERROR * - \b UART_FRAME_ERROR
* <br>Framing Error by UART * <br>Framing Error by UART
*/ */
extern unsigned int uart_getc(void); extern unsigned int uart_getc(void);
/** /**
* @brief Put byte to ringbuffer for transmitting via UART * @brief Put byte to ringbuffer for transmitting via UART
* @param data byte to be transmitted * @param data byte to be transmitted
* @return none * @return none
*/ */
extern void uart_putc(unsigned char data); extern void uart_putc(unsigned char data);
/** /**
* @brief Put string to ringbuffer for transmitting via UART * @brief Put string to ringbuffer for transmitting via UART
* *
* The string is buffered by the uart library in a circular buffer * The string is buffered by the uart library in a circular buffer
* and one character at a time is transmitted to the UART using interrupts. * and one character at a time is transmitted to the UART using interrupts.
* Blocks if it can not write the whole string into the circular buffer. * Blocks if it can not write the whole string into the circular buffer.
* *
* @param s string to be transmitted * @param s string to be transmitted
* @return none * @return none
*/ */
extern void uart_puts(const char *s ); extern void uart_puts(const char *s );
/** /**
* @brief Put string from program memory to ringbuffer for transmitting via UART. * @brief Put string from program memory to ringbuffer for transmitting via UART.
* *
* The string is buffered by the uart library in a circular buffer * The string is buffered by the uart library in a circular buffer
* and one character at a time is transmitted to the UART using interrupts. * and one character at a time is transmitted to the UART using interrupts.
* Blocks if it can not write the whole string into the circular buffer. * Blocks if it can not write the whole string into the circular buffer.
* *
* @param s program memory string to be transmitted * @param s program memory string to be transmitted
* @return none * @return none
* @see uart_puts_P * @see uart_puts_P
*/ */
extern void uart_puts_p(const char *s ); extern void uart_puts_p(const char *s );
/** /**
* @brief Macro to automatically put a string constant into program memory * @brief Macro to automatically put a string constant into program memory
*/ */
#define uart_puts_P(__s) uart_puts_p(PSTR(__s)) #define uart_puts_P(__s) uart_puts_p(PSTR(__s))
/** @brief Initialize USART1 (only available on selected ATmegas) @see uart_init */ /** @brief Initialize USART1 (only available on selected ATmegas) @see uart_init */
extern void uart1_init(unsigned int baudrate); extern void uart1_init(unsigned int baudrate);
/** @brief Get received byte of USART1 from ringbuffer. (only available on selected ATmega) @see uart_getc */ /** @brief Get received byte of USART1 from ringbuffer. (only available on selected ATmega) @see uart_getc */
extern unsigned int uart1_getc(void); extern unsigned int uart1_getc(void);
/** @brief Put byte to ringbuffer for transmitting via USART1 (only available on selected ATmega) @see uart_putc */ /** @brief Put byte to ringbuffer for transmitting via USART1 (only available on selected ATmega) @see uart_putc */
extern void uart1_putc(unsigned char data); extern void uart1_putc(unsigned char data);
/** @brief Put string to ringbuffer for transmitting via USART1 (only available on selected ATmega) @see uart_puts */ /** @brief Put string to ringbuffer for transmitting via USART1 (only available on selected ATmega) @see uart_puts */
extern void uart1_puts(const char *s ); extern void uart1_puts(const char *s );
/** @brief Put string from program memory to ringbuffer for transmitting via USART1 (only available on selected ATmega) @see uart_puts_p */ /** @brief Put string from program memory to ringbuffer for transmitting via USART1 (only available on selected ATmega) @see uart_puts_p */
extern void uart1_puts_p(const char *s ); extern void uart1_puts_p(const char *s );
/** @brief Macro to automatically put a string constant into program memory */ /** @brief Macro to automatically put a string constant into program memory */
#define uart1_puts_P(__s) uart1_puts_p(PSTR(__s)) #define uart1_puts_P(__s) uart1_puts_p(PSTR(__s))
/**@}*/ /**@}*/
#include "uart.c" #include "uart.c"
#endif // UART_H #endif // UART_H
+252 -252
View File
@@ -1,252 +1,252 @@
/* /*
Vera Arduino library is used to communicate sensor data to your Vera receiver sketch using RF24 library. Vera Arduino library is used to communicate sensor data to your Vera receiver sketch using RF24 library.
The maximum amount of transferrable data is 336 characters from a sensor to receiver. The maximum amount of transferrable data is 336 characters from a sensor to receiver.
Created by Henrik Ekblad <henrik.ekblad@gmail.com> Created by Henrik Ekblad <henrik.ekblad@gmail.com>
Version 1.0 Version 1.0
This program is free software; you can redistribute it and/or This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License modify it under the terms of the GNU General Public License
version 2 as published by the Free Software Foundation. version 2 as published by the Free Software Foundation.
modification by axillent@gmail.com to run on pure AVR modification by axillent@gmail.com to run on pure AVR
*/ */
#include "VeraAVR.h" #include "VeraAVR.h"
#include <avr/eeprom.h> #include <avr/eeprom.h>
#include <util/delay.h> #include <util/delay.h>
#include <stdlib.h> #include <stdlib.h>
uint8_t ee_radio_id EEMEM = 255; uint8_t ee_radio_id EEMEM = 255;
struct { struct {
uint16_t radioId; uint16_t radioId;
uint16_t relayId; uint16_t relayId;
message_s msg; // Buffer for incoming messages. message_s msg; // Buffer for incoming messages.
char convBuffer[20]; char convBuffer[20];
} _veraavr_data; } _veraavr_data;
/*uint8_t VeraAVR_eeprom_radioid() { /*uint8_t VeraAVR_eeprom_radioid() {
return eeprom_read_byte(&ee_radio_id); return eeprom_read_byte(&ee_radio_id);
}*/ }*/
/*static void VeraAVR_delay_ms(uint16_t delay) { /*static void VeraAVR_delay_ms(uint16_t delay) {
for(; delay >= 50; delay -= 50) { for(; delay >= 50; delay -= 50) {
_delay_ms(50); _delay_ms(50);
wdt_reset(); wdt_reset();
} }
wdt_reset(); wdt_reset();
}*/ }*/
void VeraAVR_begin(uint16_t _radioId) { void VeraAVR_begin(uint16_t _radioId) {
VeraAVR_begin2(_radioId, GATEWAY_ADDRESS); VeraAVR_begin2(_radioId, GATEWAY_ADDRESS);
} }
void VeraAVR_begin2(uint16_t _radioId, uint16_t _relayId) { void VeraAVR_begin2(uint16_t _radioId, uint16_t _relayId) {
_veraavr_data.radioId = _radioId; _veraavr_data.radioId = _radioId;
_veraavr_data.relayId = _relayId; _veraavr_data.relayId = _relayId;
// Start up the radio library // Start up the radio library
nrf24_begin(); nrf24_begin();
nrf24_enableDynamicPayloads(); nrf24_enableDynamicPayloads();
nrf24_setAutoAck(1) ; nrf24_setAutoAck(1) ;
nrf24_setRetries(15, 15); nrf24_setRetries(15, 15);
nrf24_setChannel(VERA_CHANNEL); nrf24_setChannel(VERA_CHANNEL);
nrf24_setDataRate(RF24_1MBPS); nrf24_setDataRate(RF24_1MBPS);
nrf24_setCRCLength(RF24_CRC_16); nrf24_setCRCLength(RF24_CRC_16);
if (_veraavr_data.radioId == GATEWAY_ADDRESS) { if (_veraavr_data.radioId == GATEWAY_ADDRESS) {
nrf24_openReadingPipe(1, BASE_RADIO_ID); nrf24_openReadingPipe(1, BASE_RADIO_ID);
} else { } else {
if (_veraavr_data.radioId == AUTO) { if (_veraavr_data.radioId == AUTO) {
_veraavr_data.radioId = eeprom_read_byte(&ee_radio_id); _veraavr_data.radioId = eeprom_read_byte(&ee_radio_id);
if (_veraavr_data.radioId == 0xFFF || _veraavr_data.radioId == 0x00) { if (_veraavr_data.radioId == 0xFFF || _veraavr_data.radioId == 0x00) {
// No radio id has been fetched yet. EEPROM is unwritten. // No radio id has been fetched yet. EEPROM is unwritten.
// Request new id from Vera. Use radio address 255 temporarily. // Request new id from Vera. Use radio address 255 temporarily.
//nrf24_openReadingPipe(0,0); // Don't listen to other nodes //nrf24_openReadingPipe(0,0); // Don't listen to other nodes
nrf24_openReadingPipe(1, BASE_RADIO_ID+_veraavr_data.radioId); nrf24_openReadingPipe(1, BASE_RADIO_ID+_veraavr_data.radioId);
nrf24_openWritingPipe(BASE_RADIO_ID); nrf24_openWritingPipe(BASE_RADIO_ID);
_veraavr_data.radioId = atoi(VeraAVR_getConfiguration(V_REQUEST_ID)); _veraavr_data.radioId = atoi(VeraAVR_getConfiguration(V_REQUEST_ID));
// Write id to EEPROM // Write id to EEPROM
if (_veraavr_data.radioId == AUTO) { // Vera will return 255 if all sensor id are taken if (_veraavr_data.radioId == AUTO) { // Vera will return 255 if all sensor id are taken
// wait a minute before possible wdt reset // wait a minute before possible wdt reset
for(uint8_t i=0; i < 120; i++) { for(uint8_t i=0; i < 120; i++) {
wdt_reset(); wdt_reset();
_delay_ms(500); _delay_ms(500);
} }
// wait for a while ot until wdt reset // wait for a while ot until wdt reset
while (1) {} while (1) {}
} else { } else {
eeprom_write_byte(&ee_radio_id, _veraavr_data.radioId); eeprom_write_byte(&ee_radio_id, _veraavr_data.radioId);
} }
} }
} }
//eeprom_write_byte(&ee_radio_id, _veraavr_data.radioId); //eeprom_write_byte(&ee_radio_id, _veraavr_data.radioId);
nrf24_openReadingPipe(1, BASE_RADIO_ID+_veraavr_data.radioId); nrf24_openReadingPipe(1, BASE_RADIO_ID+_veraavr_data.radioId);
} }
nrf24_startListening(); nrf24_startListening();
wdt_reset(); wdt_reset();
} }
uint8_t VeraAVR_sendDataGW(uint8_t childId, messageType messageType, uint8_t type, const char *data) { uint8_t VeraAVR_sendDataGW(uint8_t childId, messageType messageType, uint8_t type, const char *data) {
return VeraAVR_sendData(_veraavr_data.radioId, _veraavr_data.relayId, GATEWAY_ADDRESS, childId, messageType, type, data); return VeraAVR_sendData(_veraavr_data.radioId, _veraavr_data.relayId, GATEWAY_ADDRESS, childId, messageType, type, data);
} }
uint8_t VeraAVR_sendData(uint16_t from, uint16_t next, uint16_t to, uint8_t childId, messageType messageType, uint8_t type, const char *data) { uint8_t VeraAVR_sendData(uint16_t from, uint16_t next, uint16_t to, uint8_t childId, messageType messageType, uint8_t type, const char *data) {
uint8_t ok = 0; uint8_t ok = 0;
if (strlen(data) < sizeof(_veraavr_data.msg.data)) { if (strlen(data) < sizeof(_veraavr_data.msg.data)) {
_veraavr_data.msg.header.version = PROTOCOL_VERSION; _veraavr_data.msg.header.version = PROTOCOL_VERSION;
_veraavr_data.msg.header.binary = 0; _veraavr_data.msg.header.binary = 0;
_veraavr_data.msg.header.from = from; _veraavr_data.msg.header.from = from;
_veraavr_data.msg.header.to = to; _veraavr_data.msg.header.to = to;
_veraavr_data.msg.header.childId = childId; _veraavr_data.msg.header.childId = childId;
_veraavr_data.msg.header.messageType = messageType; _veraavr_data.msg.header.messageType = messageType;
_veraavr_data.msg.header.type = type; _veraavr_data.msg.header.type = type;
strncpy(_veraavr_data.msg.data, data, sizeof(_veraavr_data.msg.data)-1); strncpy(_veraavr_data.msg.data, data, sizeof(_veraavr_data.msg.data)-1);
_veraavr_data.msg.header.crc = VeraAVR_crc8Message(_veraavr_data.msg); _veraavr_data.msg.header.crc = VeraAVR_crc8Message(_veraavr_data.msg);
nrf24_stopListening(); nrf24_stopListening();
nrf24_openWritingPipe(BASE_RADIO_ID + next); nrf24_openWritingPipe(BASE_RADIO_ID + next);
uint8_t retry = 5; uint8_t retry = 5;
do { do {
ok = nrf24_write(&_veraavr_data.msg, min(MAX_MESSAGE_LENGTH, sizeof(_veraavr_data.msg.header) + strlen(_veraavr_data.msg.data) + 1)); ok = nrf24_write(&_veraavr_data.msg, min(MAX_MESSAGE_LENGTH, sizeof(_veraavr_data.msg.header) + strlen(_veraavr_data.msg.data) + 1));
wdt_reset(); wdt_reset();
} }
while ( !ok && --retry ); while ( !ok && --retry );
nrf24_startListening(); nrf24_startListening();
} }
return ok; return ok;
} }
void VeraAVR_sendVariable_char(uint8_t childId, uint8_t variableType, void VeraAVR_sendVariable_char(uint8_t childId, uint8_t variableType,
const char *value) { const char *value) {
VeraAVR_sendDataGW(childId, M_VARIABLE, variableType, value); VeraAVR_sendDataGW(childId, M_VARIABLE, variableType, value);
} }
void VeraAVR_sendVariable_float(uint8_t childId, uint8_t variableType, float value, int decimals) { void VeraAVR_sendVariable_float(uint8_t childId, uint8_t variableType, float value, int decimals) {
VeraAVR_sendVariable_char(childId, variableType, dtostrf(value,2,decimals,_veraavr_data.convBuffer)); VeraAVR_sendVariable_char(childId, variableType, dtostrf(value,2,decimals,_veraavr_data.convBuffer));
} }
void VeraAVR_sendVariable_int(uint8_t childId, uint8_t variableType, int value) { void VeraAVR_sendVariable_int(uint8_t childId, uint8_t variableType, int value) {
VeraAVR_sendVariable_char(childId, variableType, itoa(value, _veraavr_data.convBuffer, 10)); VeraAVR_sendVariable_char(childId, variableType, itoa(value, _veraavr_data.convBuffer, 10));
} }
void VeraAVR_sendVariable_long(uint8_t childId, uint8_t variableType, long value) { void VeraAVR_sendVariable_long(uint8_t childId, uint8_t variableType, long value) {
VeraAVR_sendVariable_char(childId, variableType, ltoa(value, _veraavr_data.convBuffer, 10)); VeraAVR_sendVariable_char(childId, variableType, ltoa(value, _veraavr_data.convBuffer, 10));
} }
void VeraAVR_requestStatus(uint8_t childId, uint8_t variableType) { void VeraAVR_requestStatus(uint8_t childId, uint8_t variableType) {
VeraAVR_sendDataGW(childId, M_STATUS, variableType, ""); VeraAVR_sendDataGW(childId, M_STATUS, variableType, "");
} }
char* VeraAVR_getStatus(uint8_t childId, uint8_t variableType) { char* VeraAVR_getStatus(uint8_t childId, uint8_t variableType) {
while (1) { while (1) {
VeraAVR_requestStatus(childId, variableType); VeraAVR_requestStatus(childId, variableType);
uint8_t i = 0; uint8_t i = 0;
while (i < 100) { // 5 seconds timeout before re-sending status request while (i < 100) { // 5 seconds timeout before re-sending status request
while (VeraAVR_messageAvailable()) { while (VeraAVR_messageAvailable()) {
// Check that it is right type of message and not a routing message // Check that it is right type of message and not a routing message
if ((_veraavr_data.msg.header.messageType == M_REQUEST_STATUS_RESPONSE) && if ((_veraavr_data.msg.header.messageType == M_REQUEST_STATUS_RESPONSE) &&
(_veraavr_data.msg.header.type == variableType) && (_veraavr_data.msg.header.type == variableType) &&
(_veraavr_data.msg.header.to == childId)) { (_veraavr_data.msg.header.to == childId)) {
return _veraavr_data.msg.data; return _veraavr_data.msg.data;
} }
} }
_delay_ms(50); _delay_ms(50);
wdt_reset(); wdt_reset();
i++; i++;
} }
} }
return NULL; return NULL;
} }
void VeraAVR_requestConfiguration(uint8_t variableType) { void VeraAVR_requestConfiguration(uint8_t variableType) {
VeraAVR_requestStatus(NODE_CHILD_ID, variableType); VeraAVR_requestStatus(NODE_CHILD_ID, variableType);
} }
char* VeraAVR_getConfiguration(uint8_t variableType) { char* VeraAVR_getConfiguration(uint8_t variableType) {
return VeraAVR_getStatus(NODE_CHILD_ID, variableType); return VeraAVR_getStatus(NODE_CHILD_ID, variableType);
} }
unsigned long VeraAVR_getTime() { unsigned long VeraAVR_getTime() {
return atol(VeraAVR_getConfiguration(V_TIME)); return atol(VeraAVR_getConfiguration(V_TIME));
} }
void VeraAVR_sendSensorPresentation(uint8_t childId, uint8_t sensorType) { void VeraAVR_sendSensorPresentation(uint8_t childId, uint8_t sensorType) {
VeraAVR_sendDataGW(childId, M_PRESENTATION, sensorType, LIBRARY_VERSION); VeraAVR_sendDataGW(childId, M_PRESENTATION, sensorType, LIBRARY_VERSION);
} }
uint8_t VeraAVR_messageAvailable() { uint8_t VeraAVR_messageAvailable() {
while (nrf24_available()) { while (nrf24_available()) {
VeraAVR_readMessage(); VeraAVR_readMessage();
// Check that message was addressed for me. Could be a message from some other sensor // Check that message was addressed for me. Could be a message from some other sensor
// as we«re automatically listening to pipe 0 (our writing pipe) where all sensors // as we«re automatically listening to pipe 0 (our writing pipe) where all sensors
// send their data // send their data
if (_veraavr_data.msg.header.to == _veraavr_data.radioId && VeraAVR_validate() == VALIDATE_OK) if (_veraavr_data.msg.header.to == _veraavr_data.radioId && VeraAVR_validate() == VALIDATE_OK)
return 1; return 1;
wdt_reset(); wdt_reset();
} }
return 0; return 0;
} }
message_s VeraAVR_waitForMessage() { message_s VeraAVR_waitForMessage() {
while (1) { while (1) {
if (VeraAVR_messageAvailable()) { if (VeraAVR_messageAvailable()) {
return _veraavr_data.msg; return _veraavr_data.msg;
} }
wdt_reset(); wdt_reset();
} }
} }
message_s VeraAVR_getMessage() { message_s VeraAVR_getMessage() {
return _veraavr_data.msg; return _veraavr_data.msg;
} }
message_s VeraAVR_readMessage() { message_s VeraAVR_readMessage() {
uint8_t len = nrf24_getDynamicPayloadSize(); uint8_t len = nrf24_getDynamicPayloadSize();
//uint8_t done = //uint8_t done =
nrf24_read(&_veraavr_data.msg, len); nrf24_read(&_veraavr_data.msg, len);
// Make sure string gets terminated ok. // Make sure string gets terminated ok.
_veraavr_data.msg.data[sizeof(_veraavr_data.msg.data)-1] = '\0'; _veraavr_data.msg.data[sizeof(_veraavr_data.msg.data)-1] = '\0';
return _veraavr_data.msg; return _veraavr_data.msg;
} }
/* /*
* calculate CRC8 on message_s data taking care of data structure and protocol version * calculate CRC8 on message_s data taking care of data structure and protocol version
*/ */
uint8_t VeraAVR_crc8Message(message_s var_msg) { uint8_t VeraAVR_crc8Message(message_s var_msg) {
struct { struct {
message_s msg; message_s msg;
uint8_t protocol_version; uint8_t protocol_version;
} crc_data; } crc_data;
memcpy(&crc_data, &var_msg, sizeof(var_msg)); memcpy(&crc_data, &var_msg, sizeof(var_msg));
crc_data.protocol_version = PROTOCOL_VERSION; crc_data.protocol_version = PROTOCOL_VERSION;
// some clean up needed for repeated result // some clean up needed for repeated result
crc_data.msg.header.crc = 0; crc_data.msg.header.crc = 0;
// fill unused space by zeroes for string data only // fill unused space by zeroes for string data only
if(!crc_data.msg.header.binary) { if(!crc_data.msg.header.binary) {
uint8_t len = strlen(crc_data.msg.data); uint8_t len = strlen(crc_data.msg.data);
if(len < sizeof(crc_data.msg.data)-1) { if(len < sizeof(crc_data.msg.data)-1) {
memset(&crc_data.msg.data[len], 0, sizeof(crc_data.msg.data) - 1 - len); memset(&crc_data.msg.data[len], 0, sizeof(crc_data.msg.data) - 1 - len);
} }
} }
return crc8((uint8_t*)&crc_data, (uint8_t)sizeof(crc_data)); return crc8((uint8_t*)&crc_data, (uint8_t)sizeof(crc_data));
} }
/* /*
* true if message is consistent * * true if message is consistent *
*/ */
uint8_t VeraAVR_checkCRCMessage(message_s var_msg) { uint8_t VeraAVR_checkCRCMessage(message_s var_msg) {
return (var_msg.header.crc == VeraAVR_crc8Message(var_msg))?1:0; return (var_msg.header.crc == VeraAVR_crc8Message(var_msg))?1:0;
} }
uint8_t VeraAVR_checkCRC() { uint8_t VeraAVR_checkCRC() {
return VeraAVR_checkCRCMessage(_veraavr_data.msg); return VeraAVR_checkCRCMessage(_veraavr_data.msg);
} }
uint8_t VeraAVR_validate() { uint8_t VeraAVR_validate() {
uint8_t crc_check = VeraAVR_checkCRC(); uint8_t crc_check = VeraAVR_checkCRC();
uint8_t version_check = (_veraavr_data.msg.header.version == PROTOCOL_VERSION); uint8_t version_check = (_veraavr_data.msg.header.version == PROTOCOL_VERSION);
if(crc_check && version_check) return VALIDATE_OK; if(crc_check && version_check) return VALIDATE_OK;
if(!crc_check) return VALIDATE_BAD_CRC; if(!crc_check) return VALIDATE_BAD_CRC;
return VALIDATE_BAD_VERSION; return VALIDATE_BAD_VERSION;
} }
+157 -157
View File
@@ -1,157 +1,157 @@
/* /*
Vera Arduino library is used to communicate sensor data to your Vera receiver sketch using RF24 library. Vera Arduino library is used to communicate sensor data to your Vera receiver sketch using RF24 library.
Created by Henrik Ekblad <henrik.ekblad@gmail.com> Created by Henrik Ekblad <henrik.ekblad@gmail.com>
Version 1.0 Version 1.0
This program is free software; you can redistribute it and/or This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License modify it under the terms of the GNU General Public License
version 2 as published by the Free Software Foundation. version 2 as published by the Free Software Foundation.
modification by axillent@gmail.com to run on pure AVR modification by axillent@gmail.com to run on pure AVR
before running this you need to configure properly RF24-avrlib before running this you need to configure properly RF24-avrlib
*/ */
#ifndef Vera_h #ifndef Vera_h
#define Vera_h #define Vera_h
#include <RF24/nRF24L01.h> #include <RF24/nRF24L01.h>
#include <RF24/RF24.h> #include <RF24/RF24.h>
#include <RF24/RF24_config.h> #include <RF24/RF24_config.h>
#include <crc8/crc8.h> #include <crc8/crc8.h>
#define LIBRARY_VERSION "1.2+" #define LIBRARY_VERSION "1.2+"
#define PROTOCOL_VERSION 1 #define PROTOCOL_VERSION 1
#define BAUD_RATE 115200 #define BAUD_RATE 115200
#define AUTO 0xFFF // Id 4095 is reserved for auto initialization of radioId. #define AUTO 0xFFF // Id 4095 is reserved for auto initialization of radioId.
#define NODE_CHILD_ID 0xFF // Node child id is always created for when a new sensor is detected #define NODE_CHILD_ID 0xFF // Node child id is always created for when a new sensor is detected
#define VERA_CHANNEL 76 #define VERA_CHANNEL 76
// This is the radioId for Vera receiver sketch (where all sensors should send their data). // This is the radioId for Vera receiver sketch (where all sensors should send their data).
// This is also act as base value for sensor radioId // This is also act as base value for sensor radioId
#define BASE_RADIO_ID 0xABCDABC000LL #define BASE_RADIO_ID 0xABCDABC000LL
#define GATEWAY_ADDRESS ((uint16_t)0) #define GATEWAY_ADDRESS ((uint16_t)0)
#define MAX_MESSAGE_LENGTH 32 #define MAX_MESSAGE_LENGTH 32
#define CRC8INIT 0x00 #define CRC8INIT 0x00
#define CRC8POLY 0x18 //0X18 = X^8+X^5+X^4+X^0 #define CRC8POLY 0x18 //0X18 = X^8+X^5+X^4+X^0
typedef enum { M_PRESENTATION = 0, M_VARIABLE, M_STATUS, M_CUSTOM, M_GATEWAY_MESSAGE, M_REQUEST_STATUS_RESPONSE } messageType; typedef enum { M_PRESENTATION = 0, M_VARIABLE, M_STATUS, M_CUSTOM, M_GATEWAY_MESSAGE, M_REQUEST_STATUS_RESPONSE } messageType;
// Adding new variable- and device types should be done at the end of enum // Adding new variable- and device types should be done at the end of enum
typedef enum { V_TEMP,V_HUM, V_LIGHT, V_DIMMER, V_PRESSURE, V_FORECAST, V_RAIN, V_RAINRATE, V_WIND, V_GUST, typedef enum { V_TEMP,V_HUM, V_LIGHT, V_DIMMER, V_PRESSURE, V_FORECAST, V_RAIN, V_RAINRATE, V_WIND, V_GUST,
V_DIRECTION, V_UV, V_WEIGHT, V_DISTANCE, V_IMPEDANCE, V_BATTERY_LEVEL, V_BATTERY_DATE, V_DIRECTION, V_UV, V_WEIGHT, V_DISTANCE, V_IMPEDANCE, V_BATTERY_LEVEL, V_BATTERY_DATE,
V_ARMED, V_TRIPPED, V_LAST_TRIP, V_WATT, V_KWH, V_SCENE_ON, V_SCENE_OFF, V_HEATER, V_ARMED, V_TRIPPED, V_LAST_TRIP, V_WATT, V_KWH, V_SCENE_ON, V_SCENE_OFF, V_HEATER,
V_HEATER_SW, V_LIGHT_LEVEL, V_VAR1, V_VAR2, V_VAR3, V_VAR4, V_VAR5, V_TIME, V_VERSION, V_HEATER_SW, V_LIGHT_LEVEL, V_VAR1, V_VAR2, V_VAR3, V_VAR4, V_VAR5, V_TIME, V_VERSION,
V_REQUEST_ID, V_INCLUSION_MODE, V_INCLUSION_COUNT, V_INCLUSION_RESULT, V_NEIGHBORS, V_REQUEST_ID, V_INCLUSION_MODE, V_INCLUSION_COUNT, V_INCLUSION_RESULT, V_NEIGHBORS,
V_RELAY_MODE, V_LAST_UPDATE} variable; V_RELAY_MODE, V_LAST_UPDATE} variable;
typedef enum { S_DOOR, S_MOTION, S_SMOKE, S_LIGHT, S_DIMMER, S_COVER, S_TEMP, S_HUM, S_BARO, S_WIND, typedef enum { S_DOOR, S_MOTION, S_SMOKE, S_LIGHT, S_DIMMER, S_COVER, S_TEMP, S_HUM, S_BARO, S_WIND,
S_RAIN, S_UV, S_WEIGHT, S_POWER, S_HEATER, S_DISTANCE, S_LIGHT_LEVEL, S_ARDUINO_NODE} senosr; S_RAIN, S_UV, S_WEIGHT, S_POWER, S_HEATER, S_DISTANCE, S_LIGHT_LEVEL, S_ARDUINO_NODE} senosr;
// result of validate() // result of validate()
enum { VALIDATE_OK=0, VALIDATE_BAD_CRC, VALIDATE_BAD_VERSION }; enum { VALIDATE_OK=0, VALIDATE_BAD_CRC, VALIDATE_BAD_VERSION };
typedef struct { typedef struct {
uint8_t crc : 8; // 8 bits crc uint8_t crc : 8; // 8 bits crc
uint8_t version : 3; // 3 bits protocol version uint8_t version : 3; // 3 bits protocol version
uint8_t binary : 1; // 1 bit. Data is binary and should be encoded when sent to vera uint8_t binary : 1; // 1 bit. Data is binary and should be encoded when sent to vera
uint16_t from : 12; // 12 bits. RadioId of sender node uint16_t from : 12; // 12 bits. RadioId of sender node
uint16_t to : 12; // 12 bits. RadioId of destination node uint16_t to : 12; // 12 bits. RadioId of destination node
uint8_t childId : 8; // 1 byte. Up to MAX_CHILD_DEVICES child sensors per radioId uint8_t childId : 8; // 1 byte. Up to MAX_CHILD_DEVICES child sensors per radioId
uint8_t messageType : 4; // 4 bits. Type of message. See messageType uint8_t messageType : 4; // 4 bits. Type of message. See messageType
uint8_t type : 8; // 8 bits. variableType or deviceType depending on messageType uint8_t type : 8; // 8 bits. variableType or deviceType depending on messageType
} header_s; } header_s;
typedef struct { typedef struct {
header_s header; header_s header;
char data[MAX_MESSAGE_LENGTH - sizeof(header_s) + 1]; // Each message can transfer a payload. Add one extra byte for \0 char data[MAX_MESSAGE_LENGTH - sizeof(header_s) + 1]; // Each message can transfer a payload. Add one extra byte for \0
} message_s; } message_s;
/** /**
* Begin operation of the vera library * Begin operation of the vera library
* *
* Call this in setup(), before calling any other vera library methods. * Call this in setup(), before calling any other vera library methods.
*/ */
void VeraAVR_begin(uint16_t _radioId); void VeraAVR_begin(uint16_t _radioId);
void VeraAVR_begin2(uint16_t _radioId, uint16_t _relayId); void VeraAVR_begin2(uint16_t _radioId, uint16_t _relayId);
/** /**
* Sends a variable change to vera * Sends a variable change to vera
* *
* @param childId The child id for which to update variable. Value can be 0-127. * @param childId The child id for which to update variable. Value can be 0-127.
* @param variableType The variableType to update * @param variableType The variableType to update
* @param value New value of the variable * @param value New value of the variable
*/ */
void VeraAVR_sendVariable_char (uint8_t childId, uint8_t variableType, const char *value); void VeraAVR_sendVariable_char (uint8_t childId, uint8_t variableType, const char *value);
void VeraAVR_sendVariable_float (uint8_t childId, uint8_t variableType, float value, int decimals); void VeraAVR_sendVariable_float (uint8_t childId, uint8_t variableType, float value, int decimals);
void VeraAVR_sendVariable_long(uint8_t childId, uint8_t variableType, long value); void VeraAVR_sendVariable_long(uint8_t childId, uint8_t variableType, long value);
void VeraAVR_sendVariable_int(uint8_t childId, uint8_t variableType, int value); void VeraAVR_sendVariable_int(uint8_t childId, uint8_t variableType, int value);
/** /**
* Requests status for a vera variable (sent from an actuator) * Requests status for a vera variable (sent from an actuator)
* *
* @param childId The unique child id for the different sensors connected to this arduino. 0-127. * @param childId The unique child id for the different sensors connected to this arduino. 0-127.
* @param variableType The variableType to update * @param variableType The variableType to update
*/ */
void VeraAVR_requestStatus (uint8_t childId, uint8_t variableType); void VeraAVR_requestStatus (uint8_t childId, uint8_t variableType);
/** /**
* Requests configuration parameter * Requests configuration parameter
* *
* @param variableType The variableType to fetch * @param variableType The variableType to fetch
*/ */
void VeraAVR_requestConfiguration(uint8_t variableType); void VeraAVR_requestConfiguration(uint8_t variableType);
char * VeraAVR_getConfiguration(uint8_t variableType); char * VeraAVR_getConfiguration(uint8_t variableType);
/** /**
* Fetches time from vera * Fetches time from vera
*/ */
unsigned long VeraAVR_getTime(); unsigned long VeraAVR_getTime();
/* /*
* The arduino must send a presentation of all the sensors connected before any variable changes will be registrered on Vera side. * The arduino must send a presentation of all the sensors connected before any variable changes will be registrered on Vera side.
* Usually it's good to present all sensors when Arduino starts up (setup). * Usually it's good to present all sensors when Arduino starts up (setup).
* Waits until all data has been transmitted and acknowledged by Vera receiver (retries RESEND_PRESENTATION times). * Waits until all data has been transmitted and acknowledged by Vera receiver (retries RESEND_PRESENTATION times).
* *
* @param childId The unique child id for the different sensors connected to this arduino. 0-254. * @param childId The unique child id for the different sensors connected to this arduino. 0-254.
* @param sensorType Sensor types to create. They will be numbered from 0 up to 127. * @param sensorType Sensor types to create. They will be numbered from 0 up to 127.
*/ */
void VeraAVR_sendSensorPresentation (uint8_t childId, uint8_t sensorType); void VeraAVR_sendSensorPresentation (uint8_t childId, uint8_t sensorType);
/** /**
* Registers this arduino device as a relay. This requires this node to call * Registers this arduino device as a relay. This requires this node to call
* api methods regularly to relay messages that could be passing this node and * api methods regularly to relay messages that could be passing this node and
* answer to any neighbor-discovery messages. * answer to any neighbor-discovery messages.
* Basically all api methods relays messages (waitForMessage, messageAvailable, ..) * Basically all api methods relays messages (waitForMessage, messageAvailable, ..)
* When this method is called vera will be informed that this node acts as relay. * When this method is called vera will be informed that this node acts as relay.
*/ */
void VeraAVR_registerNodeAsRelay(); void VeraAVR_registerNodeAsRelay();
/** /**
* Busy waits until there is a message available to be read (used for actuators, like relays) * Busy waits until there is a message available to be read (used for actuators, like relays)
*/ */
message_s VeraAVR_waitForVeraMessage(void); message_s VeraAVR_waitForVeraMessage(void);
/** /**
* Returns true if there is a message addressed for this node is available to be read (used by VeraGateway) * Returns true if there is a message addressed for this node is available to be read (used by VeraGateway)
*/ */
uint8_t VeraAVR_messageAvailable(); uint8_t VeraAVR_messageAvailable();
/** /**
* Returns the last received message * Returns the last received message
*/ */
message_s VeraAVR_getMessage(); message_s VeraAVR_getMessage();
uint8_t sendData(uint16_t from, uint16_t next, uint16_t to, uint8_t childId, messageType messageType, uint8_t type, const char *data); uint8_t sendData(uint16_t from, uint16_t next, uint16_t to, uint8_t childId, messageType messageType, uint8_t type, const char *data);
uint8_t VeraAVR_validate(); uint8_t VeraAVR_validate();
uint8_t VeraAVR_crc8Message(message_s); uint8_t VeraAVR_crc8Message(message_s);
uint8_t VeraAVR_checkCRCMessage(message_s); uint8_t VeraAVR_checkCRCMessage(message_s);
uint8_t VeraAVR_checkCRC(); uint8_t VeraAVR_checkCRC();
message_s VeraAVR_readMessage(void); message_s VeraAVR_readMessage(void);
uint8_t VeraAVR_sendDataGW(uint8_t childId, messageType messageType, uint8_t type, const char *data); uint8_t VeraAVR_sendDataGW(uint8_t childId, messageType messageType, uint8_t type, const char *data);
uint8_t VeraAVR_sendData(uint16_t from, uint16_t next, uint16_t to, uint8_t childId, messageType messageType, uint8_t type, const char *data); uint8_t VeraAVR_sendData(uint16_t from, uint16_t next, uint16_t to, uint8_t childId, messageType messageType, uint8_t type, const char *data);
#include "VeraAVR.c" #include "VeraAVR.c"
#endif #endif
+63 -63
View File
@@ -1,63 +1,63 @@
/* please read copyright-notice at EOF */ /* please read copyright-notice at EOF */
#include <stdint.h> #include <stdint.h>
#define CRC8INIT 0x00 #define CRC8INIT 0x00
#define CRC8POLY 0x18 //0X18 = X^8+X^5+X^4+X^0 #define CRC8POLY 0x18 //0X18 = X^8+X^5+X^4+X^0
uint8_t crc8( uint8_t *data, uint16_t number_of_bytes_in_data ) uint8_t crc8( uint8_t *data, uint16_t number_of_bytes_in_data )
{ {
uint8_t crc; uint8_t crc;
uint16_t loop_count; uint16_t loop_count;
uint8_t bit_counter; uint8_t bit_counter;
uint8_t b; uint8_t b;
uint8_t feedback_bit; uint8_t feedback_bit;
crc = CRC8INIT; crc = CRC8INIT;
for (loop_count = 0; loop_count != number_of_bytes_in_data; loop_count++) for (loop_count = 0; loop_count != number_of_bytes_in_data; loop_count++)
{ {
b = data[loop_count]; b = data[loop_count];
bit_counter = 8; bit_counter = 8;
do { do {
feedback_bit = (crc ^ b) & 0x01; feedback_bit = (crc ^ b) & 0x01;
if ( feedback_bit == 0x01 ) { if ( feedback_bit == 0x01 ) {
crc = crc ^ CRC8POLY; crc = crc ^ CRC8POLY;
} }
crc = (crc >> 1) & 0x7F; crc = (crc >> 1) & 0x7F;
if ( feedback_bit == 0x01 ) { if ( feedback_bit == 0x01 ) {
crc = crc | 0x80; crc = crc | 0x80;
} }
b = b >> 1; b = b >> 1;
bit_counter--; bit_counter--;
} while (bit_counter > 0); } while (bit_counter > 0);
} }
return crc; return crc;
} }
/* /*
This code is from Colin O'Flynn - Copyright (c) 2002 This code is from Colin O'Flynn - Copyright (c) 2002
only minor changes by M.Thomas 9/2004 only minor changes by M.Thomas 9/2004
Permission is hereby granted, free of charge, to any person obtaining a copy of 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 this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 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, the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions: subject to the following conditions:
The above copyright notice and this permission notice shall be included in all The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software. copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 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 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 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. CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/ */
+42 -42
View File
@@ -1,42 +1,42 @@
#ifndef CRC8_H_ #ifndef CRC8_H_
#define CRC8_H_ #define CRC8_H_
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
#include <stdint.h> #include <stdint.h>
uint8_t crc8( uint8_t* data, uint16_t number_of_bytes_in_data ); uint8_t crc8( uint8_t* data, uint16_t number_of_bytes_in_data );
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#include "crc8.c" #include "crc8.c"
#endif #endif
/* /*
This is based on code from : This is based on code from :
Copyright (c) 2002 Colin O'Flynn Copyright (c) 2002 Colin O'Flynn
Permission is hereby granted, free of charge, to any person obtaining a copy of 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 this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 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, the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions: subject to the following conditions:
The above copyright notice and this permission notice shall be included in all The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software. copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 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 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 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. CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/ */
@@ -1,79 +1,79 @@
#include <spi.h> #include <spi.h>
#include <ds1305.h> #include <ds1305.h>
#define DS1305_PIN 4 #define DS1305_PIN 4
#define LED_PIN 3 #define LED_PIN 3
// following two methods required by DS1305 library to select/deselect device // following two methods required by DS1305 library to select/deselect device
void select_ds1305(void) void select_ds1305(void)
{ {
digitalWrite(DS1305_PIN, HIGH); digitalWrite(DS1305_PIN, HIGH);
} }
void deselect_ds1305(void) void deselect_ds1305(void)
{ {
digitalWrite(DS1305_PIN, LOW); digitalWrite(DS1305_PIN, LOW);
} }
// flash led that's connected to pin 3 // flash led that's connected to pin 3
void flash_led(void) void flash_led(void)
{ {
pinMode(LED_PIN, OUTPUT); pinMode(LED_PIN, OUTPUT);
for (int i=0; i<10; i++) { for (int i=0; i<10; i++) {
digitalWrite(LED_PIN, i%2==0); digitalWrite(LED_PIN, i%2==0);
delay(50); delay(50);
} }
} }
// called when pin INT0 goes from 1 to 0 // called when pin INT0 goes from 1 to 0
ISR(INT0_vect) ISR(INT0_vect)
{ {
// get alarm value to clear alarm interrupt flag on DS1305 // get alarm value to clear alarm interrupt flag on DS1305
DS1305_DATETIME alarm; DS1305_DATETIME alarm;
get_alarm0(&alarm); get_alarm0(&alarm);
flash_led(); flash_led();
} }
void setup() void setup()
{ {
// flash LED at start to indicate were about to start // flash LED at start to indicate were about to start
flash_led(); flash_led();
flash_led(); flash_led();
// pin used to enable DS1305 // pin used to enable DS1305
pinMode(DS1305_PIN, OUTPUT); pinMode(DS1305_PIN, OUTPUT);
// Make sure ADC is unselected and setup spi // Make sure ADC is unselected and setup spi
deselect_ds1305(); deselect_ds1305();
setup_spi(SPI_MODE_1, SPI_MSB, SPI_NO_INTERRUPT, SPI_MSTR_CLK16); setup_spi(SPI_MODE_1, SPI_MSB, SPI_NO_INTERRUPT, SPI_MSTR_CLK16);
set_control(0); set_control(0);
// set current date/time to Thursday 06/05/09 20:32:30 // set current date/time to Thursday 06/05/09 20:32:30
DS1305_DATETIME current = {0x30, 0x32, 0x20, 0x05, 0x06, 0x05, 0x09}; DS1305_DATETIME current = {0x30, 0x32, 0x20, 0x05, 0x06, 0x05, 0x09};
set_time(&current); set_time(&current);
// change the value of alarm to the required time/granularity: // change the value of alarm to the required time/granularity:
// raise alarm every day (at 20:32:00): // raise alarm every day (at 20:32:00):
// DS1305_DATETIME alarm = {0x00, 0x32, 0x20, 0x00 | DS1305_ALARM_SET}; // DS1305_DATETIME alarm = {0x00, 0x32, 0x20, 0x00 | DS1305_ALARM_SET};
// raise alarm every minute (when seconds = 00): // raise alarm every minute (when seconds = 00):
// DS1305_DATETIME alarm = {0x00, 0x32 | DS1305_ALARM_SET, // DS1305_DATETIME alarm = {0x00, 0x32 | DS1305_ALARM_SET,
// 0x20 | DS1305_ALARM_SET, 0x05 | DS1305_ALARM_SET}; // 0x20 | DS1305_ALARM_SET, 0x05 | DS1305_ALARM_SET};
// raise alarm every second: // raise alarm every second:
DS1305_DATETIME alarm = {0x55 | DS1305_ALARM_SET, 0x32 | DS1305_ALARM_SET, DS1305_DATETIME alarm = {0x55 | DS1305_ALARM_SET, 0x32 | DS1305_ALARM_SET,
0x20 | DS1305_ALARM_SET, 0x05 | DS1305_ALARM_SET}; 0x20 | DS1305_ALARM_SET, 0x05 | DS1305_ALARM_SET};
set_alarm0(&alarm); set_alarm0(&alarm);
// turn on timer and make alarm0 lower INT0 pin when alarm is triggered // turn on timer and make alarm0 lower INT0 pin when alarm is triggered
set_control(DS1305_EOSC | DS1305_INTCN | DS1305_AIE0); set_control(DS1305_EOSC | DS1305_INTCN | DS1305_AIE0);
// raise interrupt when INT0 pin falls (pin PD0 at AT90usbXXX, pin PD2 on ATmegaXXX (arduino pin 2)) // raise interrupt when INT0 pin falls (pin PD0 at AT90usbXXX, pin PD2 on ATmegaXXX (arduino pin 2))
// the code in ISR(INT0_vect) above will be called // the code in ISR(INT0_vect) above will be called
EICRA = (1<<ISC01) | (0<<ISC00); EICRA = (1<<ISC01) | (0<<ISC00);
// enable interrupts // enable interrupts
EIMSK = (1<<INT0); EIMSK = (1<<INT0);
sei(); sei();
} }
void loop() void loop()
{ {
// do nothing - all action happens in interrupt // do nothing - all action happens in interrupt
} }
+111 -111
View File
@@ -1,111 +1,111 @@
This directory contains a simple AVR spi helper library that should This directory contains a simple AVR spi helper library that should
run on most AVR microcontrollers which support SPI. run on most AVR microcontrollers which support SPI.
The code is further described at: The code is further described at:
http://www.rocketnumbernine.com/2009/04/26/using-spi-on-an-avr-1/ (basics & ADC) http://www.rocketnumbernine.com/2009/04/26/using-spi-on-an-avr-1/ (basics & ADC)
http://www.rocketnumbernine.com/2009/05/12/using-spi-on-an-avr-2/ (RTC) http://www.rocketnumbernine.com/2009/05/12/using-spi-on-an-avr-2/ (RTC)
Any comments/questions to <andrew@rocketnumbernine.com> Any comments/questions to <andrew@rocketnumbernine.com>
Make sure viewing this text in a fixed width font for the tables and diagrams Make sure viewing this text in a fixed width font for the tables and diagrams
---------------------------------- ----------------------------------
Arduino Arduino
---------------------------------- ----------------------------------
The Arduino Directory contains all code required to run on the Arduino. The Arduino Directory contains all code required to run on the Arduino.
Simply copy the Arduino/SPI and Arduino/DS1305 directories to the Simply copy the Arduino/SPI and Arduino/DS1305 directories to the
"hardware/libraries" directory of your Arduino IDE installation and "hardware/libraries" directory of your Arduino IDE installation and
restart the Arduino IDE. Once restarted there should be restart the Arduino IDE. Once restarted there should be
"Sketch->Import Library->SPI" and "Sketch->Import Library->DS1305" menu "Sketch->Import Library->SPI" and "Sketch->Import Library->DS1305" menu
entries which can be used to include the spi header files into your project. entries which can be used to include the spi header files into your project.
"File->Sketchbook->Examples->Library SPI" contains 3 example projects "File->Sketchbook->Examples->Library SPI" contains 3 example projects
---------------------------------- ----------------------------------
AVR GCC AVR GCC
---------------------------------- ----------------------------------
To use, just copy spi.h and spi.c (and ds1305.c and ds1305.h if using To use, just copy spi.h and spi.c (and ds1305.c and ds1305.h if using
the DS1305 Real Time Clock chip) to your own project and compile. the DS1305 Real Time Clock chip) to your own project and compile.
Makefile.mf - 'standard' generated make file from AVR GCC Makefile.mf - 'standard' generated make file from AVR GCC
Makefile - Makefile "make examples" will make example programs below: Makefile - Makefile "make examples" will make example programs below:
spi-test-adc.c MC3201 Analogue to Digital convertor example spi-test-adc.c MC3201 Analogue to Digital convertor example
spi-test-rtc.c DS1305 - Real-Time-Clock/Alarm example spi-test-rtc.c DS1305 - Real-Time-Clock/Alarm example
spi-test-masterslave.c Master/Slave communication example spi-test-masterslave.c Master/Slave communication example
---------------------------------- ----------------------------------
PINS PINS
---------------------------------- ----------------------------------
Following are the AVR pins used in the circuits below Following are the AVR pins used in the circuits below
ATmegaXXX Arduino AT90usbXXX ATmegaXXX Arduino AT90usbXXX
MISO PB4 12 PB3 MISO PB4 12 PB3
MOSI PB3 11 PB2 MOSI PB3 11 PB2
SCK PB5 13 PB1 SCK PB5 13 PB1
SS PB2 10 PB0 SS PB2 10 PB0
INT0 PD2 2 PD0 INT0 PD2 2 PD0
---------------------------------- ----------------------------------
MC3201 12-bit ADC Circuit MC3201 12-bit ADC Circuit
---------------------------------- ----------------------------------
See http://ww1.microchip.com/downloads/en/DeviceDoc/21290D.pdf for full details. See http://ww1.microchip.com/downloads/en/DeviceDoc/21290D.pdf for full details.
+-----------------+ +-----------------+
| MC3201 | | MC3201 |
+5V [| Vref Vdd |] +5V +5V [| Vref Vdd |] +5V
| | | |
Analogue In [| IN+ CLK |] AVR SCK Analogue In [| IN+ CLK |] AVR SCK
| | | |
Ground [| IN- Dout |] AVR MOSI Ground [| IN- Dout |] AVR MOSI
| | | |
Ground [| Vss ^CS |] AVR CE Ground [| Vss ^CS |] AVR CE
+-----------------+ +-----------------+
For testing purposes "Analogue In" can be connected to the middle wire For testing purposes "Analogue In" can be connected to the middle wire
of a potentiometer with one outer wire being connected to +5 and the of a potentiometer with one outer wire being connected to +5 and the
other to Ground. A 1uF Capacitor should be placed between the analogue other to Ground. A 1uF Capacitor should be placed between the analogue
input and ground, and +5V and ground as close to the chip as possible, input and ground, and +5V and ground as close to the chip as possible,
but in a pinch the circuit will likely work without. but in a pinch the circuit will likely work without.
MOSI/SLCK/CE to the relevant pin on the AVR (MISO is not used) - see above. MOSI/SLCK/CE to the relevant pin on the AVR (MISO is not used) - see above.
---------------------------------- ----------------------------------
DS1305 Real Time Clock Circuit DS1305 Real Time Clock Circuit
---------------------------------- ----------------------------------
See http://datasheets.maxim-ic.com/en/ds/DS1305.pdf for full details. See http://datasheets.maxim-ic.com/en/ds/DS1305.pdf for full details.
Without a battery the following connections can be used: Without a battery the following connections can be used:
+-----------------+ +-----------------+
| DS1305 | | DS1305 |
Ground [| Vcc2 Vcc1 |] +5V Ground [| Vcc2 Vcc1 |] +5V
| | | |
Ground [| Vbat ^PF |] Not Connected Ground [| Vbat ^PF |] Not Connected
| | | |
Crystal [| X1 Vccif |] +5V Crystal [| X1 Vccif |] +5V
| | | |
Crystal [| X2 SDO |] AVR MISO Crystal [| X2 SDO |] AVR MISO
| | | |
Not Connected [| N.C. SDI |] AVR MOSI Not Connected [| N.C. SDI |] AVR MOSI
| | | |
AVR INT0 [| INT0 SLCK |] AVR SLCK AVR INT0 [| INT0 SLCK |] AVR SLCK
| | | |
Not Connected [| INT1 CE |] AVR CE Not Connected [| INT1 CE |] AVR CE
| | | |
Ground [| GND SERMODE |] +5V Ground [| GND SERMODE |] +5V
+-----------------+ +-----------------+
MISO/MOSI/SLCK/CE/INT0 to the relevant pin on the AVR - see above. MISO/MOSI/SLCK/CE/INT0 to the relevant pin on the AVR - see above.
File diff suppressed because it is too large Load Diff
+213 -213
View File
@@ -1,213 +1,213 @@
#ifndef DallasTemperature_h #ifndef DallasTemperature_h
#define DallasTemperature_h #define DallasTemperature_h
// This library is free software; you can redistribute it and/or // This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public // modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either // License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version. // version 2.1 of the License, or (at your option) any later version.
// set to true to include code for new and delete operators // set to true to include code for new and delete operators
#ifndef REQUIRESNEW #ifndef REQUIRESNEW
#define REQUIRESNEW false #define REQUIRESNEW false
#endif #endif
// set to true to include code implementing alarm search functions // set to true to include code implementing alarm search functions
#ifndef REQUIRESALARMS #ifndef REQUIRESALARMS
#define REQUIRESALARMS true #define REQUIRESALARMS true
#endif #endif
#include <inttypes.h> #include <inttypes.h>
#include <OneWire.h> #include <OneWire.h>
// Model IDs // Model IDs
#define DS18S20MODEL 0x10 #define DS18S20MODEL 0x10
#define DS18B20MODEL 0x28 #define DS18B20MODEL 0x28
#define DS1822MODEL 0x22 #define DS1822MODEL 0x22
// OneWire commands // OneWire commands
#define STARTCONVO 0x44 // Tells device to take a temperature reading and put it on the scratchpad #define STARTCONVO 0x44 // Tells device to take a temperature reading and put it on the scratchpad
#define COPYSCRATCH 0x48 // Copy EEPROM #define COPYSCRATCH 0x48 // Copy EEPROM
#define READSCRATCH 0xBE // Read EEPROM #define READSCRATCH 0xBE // Read EEPROM
#define WRITESCRATCH 0x4E // Write to EEPROM #define WRITESCRATCH 0x4E // Write to EEPROM
#define RECALLSCRATCH 0xB8 // Reload from last known #define RECALLSCRATCH 0xB8 // Reload from last known
#define READPOWERSUPPLY 0xB4 // Determine if device needs parasite power #define READPOWERSUPPLY 0xB4 // Determine if device needs parasite power
#define ALARMSEARCH 0xEC // Query bus for devices with an alarm condition #define ALARMSEARCH 0xEC // Query bus for devices with an alarm condition
// Scratchpad locations // Scratchpad locations
#define TEMP_LSB 0 #define TEMP_LSB 0
#define TEMP_MSB 1 #define TEMP_MSB 1
#define HIGH_ALARM_TEMP 2 #define HIGH_ALARM_TEMP 2
#define LOW_ALARM_TEMP 3 #define LOW_ALARM_TEMP 3
#define CONFIGURATION 4 #define CONFIGURATION 4
#define INTERNAL_BYTE 5 #define INTERNAL_BYTE 5
#define COUNT_REMAIN 6 #define COUNT_REMAIN 6
#define COUNT_PER_C 7 #define COUNT_PER_C 7
#define SCRATCHPAD_CRC 8 #define SCRATCHPAD_CRC 8
// Device resolution // Device resolution
#define TEMP_9_BIT 0x1F // 9 bit #define TEMP_9_BIT 0x1F // 9 bit
#define TEMP_10_BIT 0x3F // 10 bit #define TEMP_10_BIT 0x3F // 10 bit
#define TEMP_11_BIT 0x5F // 11 bit #define TEMP_11_BIT 0x5F // 11 bit
#define TEMP_12_BIT 0x7F // 12 bit #define TEMP_12_BIT 0x7F // 12 bit
// Error Codes // Error Codes
#define DEVICE_DISCONNECTED -127 #define DEVICE_DISCONNECTED -127
typedef uint8_t DeviceAddress[8]; typedef uint8_t DeviceAddress[8];
class DallasTemperature class DallasTemperature
{ {
public: public:
DallasTemperature(OneWire*); DallasTemperature(OneWire*);
// initalize bus // initalize bus
void begin(void); void begin(void);
// returns the number of devices found on the bus // returns the number of devices found on the bus
uint8_t getDeviceCount(void); uint8_t getDeviceCount(void);
// returns true if address is valid // returns true if address is valid
bool validAddress(uint8_t*); bool validAddress(uint8_t*);
// finds an address at a given index on the bus // finds an address at a given index on the bus
bool getAddress(uint8_t*, const uint8_t); bool getAddress(uint8_t*, const uint8_t);
// attempt to determine if the device at the given address is connected to the bus // attempt to determine if the device at the given address is connected to the bus
bool isConnected(uint8_t*); bool isConnected(uint8_t*);
// attempt to determine if the device at the given address is connected to the bus // attempt to determine if the device at the given address is connected to the bus
// also allows for updating the read scratchpad // also allows for updating the read scratchpad
bool isConnected(uint8_t*, uint8_t*); bool isConnected(uint8_t*, uint8_t*);
// read device's scratchpad // read device's scratchpad
void readScratchPad(uint8_t*, uint8_t*); void readScratchPad(uint8_t*, uint8_t*);
// write device's scratchpad // write device's scratchpad
void writeScratchPad(uint8_t*, const uint8_t*); void writeScratchPad(uint8_t*, const uint8_t*);
// read device's power requirements // read device's power requirements
bool readPowerSupply(uint8_t*); bool readPowerSupply(uint8_t*);
// returns the current resolution, 9-12 // returns the current resolution, 9-12
uint8_t getResolution(uint8_t*); uint8_t getResolution(uint8_t*);
// set resolution of a device to 9, 10, 11, or 12 bits // set resolution of a device to 9, 10, 11, or 12 bits
void setResolution(uint8_t*, uint8_t); void setResolution(uint8_t*, uint8_t);
// sends command for all devices on the bus to perform a temperature conversion // sends command for all devices on the bus to perform a temperature conversion
void requestTemperatures(void); void requestTemperatures(void);
// sends command for one device to perform a temperature conversion by address // sends command for one device to perform a temperature conversion by address
void requestTemperaturesByAddress(uint8_t*); void requestTemperaturesByAddress(uint8_t*);
// sends command for one device to perform a temperature conversion by index // sends command for one device to perform a temperature conversion by index
void requestTemperaturesByIndex(uint8_t); void requestTemperaturesByIndex(uint8_t);
// returns temperature in degrees C // returns temperature in degrees C
float getTempC(uint8_t*); float getTempC(uint8_t*);
// returns temperature in degrees F // returns temperature in degrees F
float getTempF(uint8_t*); float getTempF(uint8_t*);
// Get temperature for device index (slow) // Get temperature for device index (slow)
float getTempCByIndex(uint8_t); float getTempCByIndex(uint8_t);
// Get temperature for device index (slow) // Get temperature for device index (slow)
float getTempFByIndex(uint8_t); float getTempFByIndex(uint8_t);
// returns true if the bus requires parasite power // returns true if the bus requires parasite power
bool isParasitePowerMode(void); bool isParasitePowerMode(void);
#if REQUIRESALARMS #if REQUIRESALARMS
typedef void AlarmHandler(uint8_t*); typedef void AlarmHandler(uint8_t*);
// sets the high alarm temperature for a device // sets the high alarm temperature for a device
// accepts a char. valid range is -55C - 125C // accepts a char. valid range is -55C - 125C
void setHighAlarmTemp(uint8_t*, const char); void setHighAlarmTemp(uint8_t*, const char);
// sets the low alarm temperature for a device // sets the low alarm temperature for a device
// accepts a char. valid range is -55C - 125C // accepts a char. valid range is -55C - 125C
void setLowAlarmTemp(uint8_t*, const char); void setLowAlarmTemp(uint8_t*, const char);
// returns a signed char with the current high alarm temperature for a device // returns a signed char with the current high alarm temperature for a device
// in the range -55C - 125C // in the range -55C - 125C
char getHighAlarmTemp(uint8_t*); char getHighAlarmTemp(uint8_t*);
// returns a signed char with the current low alarm temperature for a device // returns a signed char with the current low alarm temperature for a device
// in the range -55C - 125C // in the range -55C - 125C
char getLowAlarmTemp(uint8_t*); char getLowAlarmTemp(uint8_t*);
// resets internal variables used for the alarm search // resets internal variables used for the alarm search
void resetAlarmSearch(void); void resetAlarmSearch(void);
// search the wire for devices with active alarms // search the wire for devices with active alarms
bool alarmSearch(uint8_t*); bool alarmSearch(uint8_t*);
// returns true if ia specific device has an alarm // returns true if ia specific device has an alarm
bool hasAlarm(uint8_t*); bool hasAlarm(uint8_t*);
// returns true if any device is reporting an alarm on the bus // returns true if any device is reporting an alarm on the bus
bool hasAlarm(void); bool hasAlarm(void);
// runs the alarm handler for all devices returned by alarmSearch() // runs the alarm handler for all devices returned by alarmSearch()
void processAlarms(void); void processAlarms(void);
// sets the alarm handler // sets the alarm handler
void setAlarmHandler(AlarmHandler *); void setAlarmHandler(AlarmHandler *);
// The default alarm handler // The default alarm handler
static void defaultAlarmHandler(uint8_t*); static void defaultAlarmHandler(uint8_t*);
#endif #endif
// convert from celcius to farenheit // convert from celcius to farenheit
static float toFahrenheit(const float); static float toFahrenheit(const float);
// convert from farenheit to celsius // convert from farenheit to celsius
static float toCelsius(const float); static float toCelsius(const float);
#if REQUIRESNEW #if REQUIRESNEW
// initalize memory area // initalize memory area
void* operator new (unsigned int); void* operator new (unsigned int);
// delete memory reference // delete memory reference
void operator delete(void*); void operator delete(void*);
#endif #endif
private: private:
typedef uint8_t ScratchPad[9]; typedef uint8_t ScratchPad[9];
// parasite power on or off // parasite power on or off
bool parasite; bool parasite;
// used to determine the delay amount needed to allow for the // used to determine the delay amount needed to allow for the
// temperature conversion to take place // temperature conversion to take place
int conversionDelay; int conversionDelay;
// count of devices on the bus // count of devices on the bus
uint8_t devices; uint8_t devices;
// Take a pointer to one wire instance // Take a pointer to one wire instance
OneWire* _wire; OneWire* _wire;
// reads scratchpad and returns the temperature in degrees C // reads scratchpad and returns the temperature in degrees C
float calculateTemperature(uint8_t*, uint8_t*); float calculateTemperature(uint8_t*, uint8_t*);
#if REQUIRESALARMS #if REQUIRESALARMS
// required for alarmSearch // required for alarmSearch
uint8_t alarmSearchAddress[8]; uint8_t alarmSearchAddress[8];
char alarmSearchJunction; char alarmSearchJunction;
uint8_t alarmSearchExhausted; uint8_t alarmSearchExhausted;
// the alarm handler function pointer // the alarm handler function pointer
AlarmHandler *_AlarmHandler; AlarmHandler *_AlarmHandler;
#endif #endif
}; };
#endif #endif
@@ -159,4 +159,4 @@ void loop(void)
*/ */
} }
@@ -142,4 +142,4 @@ void loop(void)
delay(1000); delay(1000);
} }
@@ -137,4 +137,4 @@ void loop(void)
printData(insideThermometer); printData(insideThermometer);
printData(outsideThermometer); printData(outsideThermometer);
} }
@@ -30,4 +30,4 @@ void loop(void)
Serial.print("Temperature for the device 1 (index 0) is: "); Serial.print("Temperature for the device 1 (index 0) is: ");
Serial.println(sensors.getTempCByIndex(0)); Serial.println(sensors.getTempCByIndex(0));
} }
@@ -106,4 +106,4 @@ void printAddress(DeviceAddress deviceAddress)
if (deviceAddress[i] < 16) Serial.print("0"); if (deviceAddress[i] < 16) Serial.print("0");
Serial.print(deviceAddress[i], HEX); Serial.print(deviceAddress[i], HEX);
} }
} }
@@ -121,4 +121,4 @@ void printAddress(DeviceAddress deviceAddress)
if (deviceAddress[i] < 16) Serial.print("0"); if (deviceAddress[i] < 16) Serial.print("0");
Serial.print(deviceAddress[i], HEX); Serial.print(deviceAddress[i], HEX);
} }
} }
+35 -35
View File
@@ -1,36 +1,36 @@
InterruptChain library v1.3.0 (20130601) for Arduino 1.0 InterruptChain library v1.3.0 (20130601) for Arduino 1.0
Made by Randy Simons http://randysimons.nl/ Made by Randy Simons http://randysimons.nl/
This library allows for daisychaining the interrupts, i.e. you can attach This library allows for daisychaining the interrupts, i.e. you can attach
more than one interrupt handler to a single interrupt. more than one interrupt handler to a single interrupt.
See the examples for usage. See InterruptChainLib.h for details! See the examples for usage. See InterruptChainLib.h for details!
License: GPLv3. See ./InterruptChain/license.txt License: GPLv3. See ./InterruptChain/license.txt
Latest source and wiki: https://bitbucket.org/fuzzillogic/433mhzforarduino Latest source and wiki: https://bitbucket.org/fuzzillogic/433mhzforarduino
Installation of library: Installation of library:
- Make sure Arduino is closed - Make sure Arduino is closed
- Copy the directory InterruptChain to the Arduino library directory (usually - Copy the directory InterruptChain to the Arduino library directory (usually
<Sketchbook directory>/libraries/) <Sketchbook directory>/libraries/)
See http://arduino.cc/en/Guide/Libraries for detailed instructions. See http://arduino.cc/en/Guide/Libraries for detailed instructions.
Examples are provided. Examples are provided.
Changelog: Changelog:
InterruptChain library v1.3.0 (20130601) for Arduino 1.0 InterruptChain library v1.3.0 (20130601) for Arduino 1.0
- Dropped support for Arduino pre-1.0 - Dropped support for Arduino pre-1.0
- Doesn't use recursion internally, and fewer function calls. This should save - Doesn't use recursion internally, and fewer function calls. This should save
some extra bytes in RAM, at the cost of moderately increased Flash usage. some extra bytes in RAM, at the cost of moderately increased Flash usage.
InterruptChain library v1.2.0 (20120213) for Arduino 0022/1.0 InterruptChain library v1.2.0 (20120213) for Arduino 0022/1.0
- Support for Arduino 1.0. - Support for Arduino 1.0.
InterruptChain library v1.1.0 (20110921) for Arduino 0022 InterruptChain library v1.1.0 (20110921) for Arduino 0022
- Added enable, disable. Expanded setMode. - Added enable, disable. Expanded setMode.
InterruptChain library v1.0.0 (20110919) for Arduino 0022 InterruptChain library v1.0.0 (20110919) for Arduino 0022
- First release - First release
+4 -4
View File
@@ -1,5 +1,5 @@
InterruptChain KEYWORD1 InterruptChain KEYWORD1
addInterruptCallback KEYWORD2 addInterruptCallback KEYWORD2
setMode KEYWORD2 setMode KEYWORD2
enable KEYWORD2 enable KEYWORD2
disable KEYWORD2 disable KEYWORD2
+231 -231
View File
@@ -1,231 +1,231 @@
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// Created by Tim Eckel - teckel@leethost.com // Created by Tim Eckel - teckel@leethost.com
// Copyright 2012 License: GNU GPL v3 http://www.gnu.org/licenses/gpl-3.0.html // Copyright 2012 License: GNU GPL v3 http://www.gnu.org/licenses/gpl-3.0.html
// //
// See "NewPing.h" for purpose, syntax, version history, links, and more. // See "NewPing.h" for purpose, syntax, version history, links, and more.
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
#include "NewPing.h" #include "NewPing.h"
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// NewPing constructor // NewPing constructor
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
NewPing::NewPing(uint8_t trigger_pin, uint8_t echo_pin, int max_cm_distance) { NewPing::NewPing(uint8_t trigger_pin, uint8_t echo_pin, int max_cm_distance) {
_triggerBit = digitalPinToBitMask(trigger_pin); // Get the port register bitmask for the trigger pin. _triggerBit = digitalPinToBitMask(trigger_pin); // Get the port register bitmask for the trigger pin.
_echoBit = digitalPinToBitMask(echo_pin); // Get the port register bitmask for the echo pin. _echoBit = digitalPinToBitMask(echo_pin); // Get the port register bitmask for the echo pin.
_triggerOutput = portOutputRegister(digitalPinToPort(trigger_pin)); // Get the output port register for the trigger pin. _triggerOutput = portOutputRegister(digitalPinToPort(trigger_pin)); // Get the output port register for the trigger pin.
_echoInput = portInputRegister(digitalPinToPort(echo_pin)); // Get the input port register for the echo pin. _echoInput = portInputRegister(digitalPinToPort(echo_pin)); // Get the input port register for the echo pin.
_triggerMode = (uint8_t *) portModeRegister(digitalPinToPort(trigger_pin)); // Get the port mode register for the trigger pin. _triggerMode = (uint8_t *) portModeRegister(digitalPinToPort(trigger_pin)); // Get the port mode register for the trigger pin.
_maxEchoTime = min(max_cm_distance, MAX_SENSOR_DISTANCE) * US_ROUNDTRIP_CM + (US_ROUNDTRIP_CM / 2); // Calculate the maximum distance in uS. _maxEchoTime = min(max_cm_distance, MAX_SENSOR_DISTANCE) * US_ROUNDTRIP_CM + (US_ROUNDTRIP_CM / 2); // Calculate the maximum distance in uS.
#if DISABLE_ONE_PIN == true #if DISABLE_ONE_PIN == true
*_triggerMode |= _triggerBit; // Set trigger pin to output. *_triggerMode |= _triggerBit; // Set trigger pin to output.
#endif #endif
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// Standard ping methods // Standard ping methods
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
unsigned int NewPing::ping() { unsigned int NewPing::ping() {
if (!ping_trigger()) return NO_ECHO; // Trigger a ping, if it returns false, return NO_ECHO to the calling function. if (!ping_trigger()) return NO_ECHO; // Trigger a ping, if it returns false, return NO_ECHO to the calling function.
while (*_echoInput & _echoBit) // Wait for the ping echo. while (*_echoInput & _echoBit) // Wait for the ping echo.
if (micros() > _max_time) return NO_ECHO; // Stop the loop and return NO_ECHO (false) if we're beyond the set maximum distance. if (micros() > _max_time) return NO_ECHO; // Stop the loop and return NO_ECHO (false) if we're beyond the set maximum distance.
return (micros() - (_max_time - _maxEchoTime) - 5); // Calculate ping time, 5uS of overhead. return (micros() - (_max_time - _maxEchoTime) - 5); // Calculate ping time, 5uS of overhead.
} }
unsigned int NewPing::ping_in() { unsigned int NewPing::ping_in() {
unsigned int echoTime = NewPing::ping(); // Calls the ping method and returns with the ping echo distance in uS. unsigned int echoTime = NewPing::ping(); // Calls the ping method and returns with the ping echo distance in uS.
return NewPingConvert(echoTime, US_ROUNDTRIP_IN); // Convert uS to inches. return NewPingConvert(echoTime, US_ROUNDTRIP_IN); // Convert uS to inches.
} }
unsigned int NewPing::ping_cm() { unsigned int NewPing::ping_cm() {
unsigned int echoTime = NewPing::ping(); // Calls the ping method and returns with the ping echo distance in uS. unsigned int echoTime = NewPing::ping(); // Calls the ping method and returns with the ping echo distance in uS.
return NewPingConvert(echoTime, US_ROUNDTRIP_CM); // Convert uS to centimeters. return NewPingConvert(echoTime, US_ROUNDTRIP_CM); // Convert uS to centimeters.
} }
unsigned int NewPing::ping_median(uint8_t it) { unsigned int NewPing::ping_median(uint8_t it) {
unsigned int uS[it], last; unsigned int uS[it], last;
uint8_t j, i = 0; uint8_t j, i = 0;
uS[0] = NO_ECHO; uS[0] = NO_ECHO;
while (i < it) { while (i < it) {
last = ping(); // Send ping. last = ping(); // Send ping.
if (last == NO_ECHO) { // Ping out of range. if (last == NO_ECHO) { // Ping out of range.
it--; // Skip, don't include as part of median. it--; // Skip, don't include as part of median.
last = _maxEchoTime; // Adjust "last" variable so delay is correct length. last = _maxEchoTime; // Adjust "last" variable so delay is correct length.
} else { // Ping in range, include as part of median. } else { // Ping in range, include as part of median.
if (i > 0) { // Don't start sort till second ping. if (i > 0) { // Don't start sort till second ping.
for (j = i; j > 0 && uS[j - 1] < last; j--) // Insertion sort loop. for (j = i; j > 0 && uS[j - 1] < last; j--) // Insertion sort loop.
uS[j] = uS[j - 1]; // Shift ping array to correct position for sort insertion. uS[j] = uS[j - 1]; // Shift ping array to correct position for sort insertion.
} else j = 0; // First ping is starting point for sort. } else j = 0; // First ping is starting point for sort.
uS[j] = last; // Add last ping to array in sorted position. uS[j] = last; // Add last ping to array in sorted position.
i++; // Move to next ping. i++; // Move to next ping.
} }
if (i < it) delay(PING_MEDIAN_DELAY - (last >> 10)); // Millisecond delay between pings. if (i < it) delay(PING_MEDIAN_DELAY - (last >> 10)); // Millisecond delay between pings.
} }
return (uS[it >> 1]); // Return the ping distance median. return (uS[it >> 1]); // Return the ping distance median.
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// Standard ping method support functions (not called directly) // Standard ping method support functions (not called directly)
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
boolean NewPing::ping_trigger() { boolean NewPing::ping_trigger() {
#if DISABLE_ONE_PIN != true #if DISABLE_ONE_PIN != true
*_triggerMode |= _triggerBit; // Set trigger pin to output. *_triggerMode |= _triggerBit; // Set trigger pin to output.
#endif #endif
*_triggerOutput &= ~_triggerBit; // Set the trigger pin low, should already be low, but this will make sure it is. *_triggerOutput &= ~_triggerBit; // Set the trigger pin low, should already be low, but this will make sure it is.
delayMicroseconds(4); // Wait for pin to go low, testing shows it needs 4uS to work every time. delayMicroseconds(4); // Wait for pin to go low, testing shows it needs 4uS to work every time.
*_triggerOutput |= _triggerBit; // Set trigger pin high, this tells the sensor to send out a ping. *_triggerOutput |= _triggerBit; // Set trigger pin high, this tells the sensor to send out a ping.
delayMicroseconds(10); // Wait long enough for the sensor to realize the trigger pin is high. Sensor specs say to wait 10uS. delayMicroseconds(10); // Wait long enough for the sensor to realize the trigger pin is high. Sensor specs say to wait 10uS.
*_triggerOutput &= ~_triggerBit; // Set trigger pin back to low. *_triggerOutput &= ~_triggerBit; // Set trigger pin back to low.
#if DISABLE_ONE_PIN != true #if DISABLE_ONE_PIN != true
*_triggerMode &= ~_triggerBit; // Set trigger pin to input (when using one Arduino pin this is technically setting the echo pin to input as both are tied to the same Arduino pin). *_triggerMode &= ~_triggerBit; // Set trigger pin to input (when using one Arduino pin this is technically setting the echo pin to input as both are tied to the same Arduino pin).
#endif #endif
_max_time = micros() + MAX_SENSOR_DELAY; // Set a timeout for the ping to trigger. _max_time = micros() + MAX_SENSOR_DELAY; // Set a timeout for the ping to trigger.
while (*_echoInput & _echoBit && micros() <= _max_time) {} // Wait for echo pin to clear. while (*_echoInput & _echoBit && micros() <= _max_time) {} // Wait for echo pin to clear.
while (!(*_echoInput & _echoBit)) // Wait for ping to start. while (!(*_echoInput & _echoBit)) // Wait for ping to start.
if (micros() > _max_time) return false; // Something went wrong, abort. if (micros() > _max_time) return false; // Something went wrong, abort.
_max_time = micros() + _maxEchoTime; // Ping started, set the timeout. _max_time = micros() + _maxEchoTime; // Ping started, set the timeout.
return true; // Ping started successfully. return true; // Ping started successfully.
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// Timer interrupt ping methods (won't work with ATmega8 and ATmega128) // Timer interrupt ping methods (won't work with ATmega8 and ATmega128)
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
void NewPing::ping_timer(void (*userFunc)(void)) { void NewPing::ping_timer(void (*userFunc)(void)) {
if (!ping_trigger()) return; // Trigger a ping, if it returns false, return without starting the echo timer. if (!ping_trigger()) return; // Trigger a ping, if it returns false, return without starting the echo timer.
timer_us(ECHO_TIMER_FREQ, userFunc); // Set ping echo timer check every ECHO_TIMER_FREQ uS. timer_us(ECHO_TIMER_FREQ, userFunc); // Set ping echo timer check every ECHO_TIMER_FREQ uS.
} }
boolean NewPing::check_timer() { boolean NewPing::check_timer() {
if (micros() > _max_time) { // Outside the timeout limit. if (micros() > _max_time) { // Outside the timeout limit.
timer_stop(); // Disable timer interrupt timer_stop(); // Disable timer interrupt
return false; // Cancel ping timer. return false; // Cancel ping timer.
} }
if (!(*_echoInput & _echoBit)) { // Ping echo received. if (!(*_echoInput & _echoBit)) { // Ping echo received.
timer_stop(); // Disable timer interrupt timer_stop(); // Disable timer interrupt
ping_result = (micros() - (_max_time - _maxEchoTime) - 13); // Calculate ping time, 13uS of overhead. ping_result = (micros() - (_max_time - _maxEchoTime) - 13); // Calculate ping time, 13uS of overhead.
return true; // Return ping echo true. return true; // Return ping echo true.
} }
return false; // Return false because there's no ping echo yet. return false; // Return false because there's no ping echo yet.
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// Timer2/Timer4 interrupt methods (can be used for non-ultrasonic needs) // Timer2/Timer4 interrupt methods (can be used for non-ultrasonic needs)
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// Variables used for timer functions // Variables used for timer functions
void (*intFunc)(); void (*intFunc)();
void (*intFunc2)(); void (*intFunc2)();
unsigned long _ms_cnt_reset; unsigned long _ms_cnt_reset;
volatile unsigned long _ms_cnt; volatile unsigned long _ms_cnt;
void NewPing::timer_us(unsigned int frequency, void (*userFunc)(void)) { void NewPing::timer_us(unsigned int frequency, void (*userFunc)(void)) {
timer_setup(); // Configure the timer interrupt. timer_setup(); // Configure the timer interrupt.
intFunc = userFunc; // User's function to call when there's a timer event. intFunc = userFunc; // User's function to call when there's a timer event.
#if defined (__AVR_ATmega32U4__) // Use Timer4 for ATmega32U4 (Teensy/Leonardo). #if defined (__AVR_ATmega32U4__) // Use Timer4 for ATmega32U4 (Teensy/Leonardo).
OCR4C = min((frequency>>2) - 1, 255); // Every count is 4uS, so divide by 4 (bitwise shift right 2) subtract one, then make sure we don't go over 255 limit. OCR4C = min((frequency>>2) - 1, 255); // Every count is 4uS, so divide by 4 (bitwise shift right 2) subtract one, then make sure we don't go over 255 limit.
TIMSK4 = (1<<TOIE4); // Enable Timer4 interrupt. TIMSK4 = (1<<TOIE4); // Enable Timer4 interrupt.
#else #else
OCR2A = min((frequency>>2) - 1, 255); // Every count is 4uS, so divide by 4 (bitwise shift right 2) subtract one, then make sure we don't go over 255 limit. OCR2A = min((frequency>>2) - 1, 255); // Every count is 4uS, so divide by 4 (bitwise shift right 2) subtract one, then make sure we don't go over 255 limit.
TIMSK2 |= (1<<OCIE2A); // Enable Timer2 interrupt. TIMSK2 |= (1<<OCIE2A); // Enable Timer2 interrupt.
#endif #endif
} }
void NewPing::timer_ms(unsigned long frequency, void (*userFunc)(void)) { void NewPing::timer_ms(unsigned long frequency, void (*userFunc)(void)) {
timer_setup(); // Configure the timer interrupt. timer_setup(); // Configure the timer interrupt.
intFunc = NewPing::timer_ms_cntdwn; // Timer events are sent here once every ms till user's frequency is reached. intFunc = NewPing::timer_ms_cntdwn; // Timer events are sent here once every ms till user's frequency is reached.
intFunc2 = userFunc; // User's function to call when user's frequency is reached. intFunc2 = userFunc; // User's function to call when user's frequency is reached.
_ms_cnt = _ms_cnt_reset = frequency; // Current ms counter and reset value. _ms_cnt = _ms_cnt_reset = frequency; // Current ms counter and reset value.
#if defined (__AVR_ATmega32U4__) // Use Timer4 for ATmega32U4 (Teensy/Leonardo). #if defined (__AVR_ATmega32U4__) // Use Timer4 for ATmega32U4 (Teensy/Leonardo).
OCR4C = 249; // Every count is 4uS, so 1ms = 250 counts - 1. OCR4C = 249; // Every count is 4uS, so 1ms = 250 counts - 1.
TIMSK4 = (1<<TOIE4); // Enable Timer4 interrupt. TIMSK4 = (1<<TOIE4); // Enable Timer4 interrupt.
#else #else
OCR2A = 249; // Every count is 4uS, so 1ms = 250 counts - 1. OCR2A = 249; // Every count is 4uS, so 1ms = 250 counts - 1.
TIMSK2 |= (1<<OCIE2A); // Enable Timer2 interrupt. TIMSK2 |= (1<<OCIE2A); // Enable Timer2 interrupt.
#endif #endif
} }
void NewPing::timer_stop() { // Disable timer interrupt. void NewPing::timer_stop() { // Disable timer interrupt.
#if defined (__AVR_ATmega32U4__) // Use Timer4 for ATmega32U4 (Teensy/Leonardo). #if defined (__AVR_ATmega32U4__) // Use Timer4 for ATmega32U4 (Teensy/Leonardo).
TIMSK4 = 0; TIMSK4 = 0;
#else #else
TIMSK2 &= ~(1<<OCIE2A); TIMSK2 &= ~(1<<OCIE2A);
#endif #endif
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// Timer2/Timer4 interrupt method support functions (not called directly) // Timer2/Timer4 interrupt method support functions (not called directly)
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
void NewPing::timer_setup() { void NewPing::timer_setup() {
#if defined (__AVR_ATmega32U4__) // Use Timer4 for ATmega32U4 (Teensy/Leonardo). #if defined (__AVR_ATmega32U4__) // Use Timer4 for ATmega32U4 (Teensy/Leonardo).
timer_stop(); // Disable Timer4 interrupt. timer_stop(); // Disable Timer4 interrupt.
TCCR4A = TCCR4C = TCCR4D = TCCR4E = 0; TCCR4A = TCCR4C = TCCR4D = TCCR4E = 0;
TCCR4B = (1<<CS42) | (1<<CS41) | (1<<CS40) | (1<<PSR4); // Set Timer4 prescaler to 64 (4uS/count, 4uS-1020uS range). TCCR4B = (1<<CS42) | (1<<CS41) | (1<<CS40) | (1<<PSR4); // Set Timer4 prescaler to 64 (4uS/count, 4uS-1020uS range).
TIFR4 = (1<<TOV4); TIFR4 = (1<<TOV4);
TCNT4 = 0; // Reset Timer4 counter. TCNT4 = 0; // Reset Timer4 counter.
#else #else
timer_stop(); // Disable Timer2 interrupt. timer_stop(); // Disable Timer2 interrupt.
ASSR &= ~(1<<AS2); // Set clock, not pin. ASSR &= ~(1<<AS2); // Set clock, not pin.
TCCR2A = (1<<WGM21); // Set Timer2 to CTC mode. TCCR2A = (1<<WGM21); // Set Timer2 to CTC mode.
TCCR2B = (1<<CS22); // Set Timer2 prescaler to 64 (4uS/count, 4uS-1020uS range). TCCR2B = (1<<CS22); // Set Timer2 prescaler to 64 (4uS/count, 4uS-1020uS range).
TCNT2 = 0; // Reset Timer2 counter. TCNT2 = 0; // Reset Timer2 counter.
#endif #endif
} }
void NewPing::timer_ms_cntdwn() { void NewPing::timer_ms_cntdwn() {
if (!_ms_cnt--) { // Count down till we reach zero. if (!_ms_cnt--) { // Count down till we reach zero.
intFunc2(); // Scheduled time reached, run the main timer event function. intFunc2(); // Scheduled time reached, run the main timer event function.
_ms_cnt = _ms_cnt_reset; // Reset the ms timer. _ms_cnt = _ms_cnt_reset; // Reset the ms timer.
} }
} }
#if defined (__AVR_ATmega32U4__) // Use Timer4 for ATmega32U4 (Teensy/Leonardo). #if defined (__AVR_ATmega32U4__) // Use Timer4 for ATmega32U4 (Teensy/Leonardo).
ISR(TIMER4_OVF_vect) { ISR(TIMER4_OVF_vect) {
#else #else
ISR(TIMER2_COMPA_vect) { ISR(TIMER2_COMPA_vect) {
#endif #endif
if(intFunc) intFunc(); // If wrapped function is set, call it. if(intFunc) intFunc(); // If wrapped function is set, call it.
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// Conversion methods (rounds result to nearest inch or cm). // Conversion methods (rounds result to nearest inch or cm).
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
unsigned int NewPing::convert_in(unsigned int echoTime) { unsigned int NewPing::convert_in(unsigned int echoTime) {
return NewPingConvert(echoTime, US_ROUNDTRIP_IN); // Convert uS to inches. return NewPingConvert(echoTime, US_ROUNDTRIP_IN); // Convert uS to inches.
} }
unsigned int NewPing::convert_cm(unsigned int echoTime) { unsigned int NewPing::convert_cm(unsigned int echoTime) {
return NewPingConvert(echoTime, US_ROUNDTRIP_CM); // Convert uS to centimeters. return NewPingConvert(echoTime, US_ROUNDTRIP_CM); // Convert uS to centimeters.
} }
+161 -161
View File
@@ -1,162 +1,162 @@
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// NewPing Library - v1.5 - 08/15/2012 // NewPing Library - v1.5 - 08/15/2012
// //
// AUTHOR/LICENSE: // AUTHOR/LICENSE:
// Created by Tim Eckel - teckel@leethost.com // Created by Tim Eckel - teckel@leethost.com
// Copyright 2012 License: GNU GPL v3 http://www.gnu.org/licenses/gpl-3.0.html // Copyright 2012 License: GNU GPL v3 http://www.gnu.org/licenses/gpl-3.0.html
// //
// LINKS: // LINKS:
// Project home: http://code.google.com/p/arduino-new-ping/ // Project home: http://code.google.com/p/arduino-new-ping/
// Blog: http://arduino.cc/forum/index.php/topic,106043.0.html // Blog: http://arduino.cc/forum/index.php/topic,106043.0.html
// //
// DISCLAIMER: // DISCLAIMER:
// This software is furnished "as is", without technical support, and with no // This software is furnished "as is", without technical support, and with no
// warranty, express or implied, as to its usefulness for any purpose. // warranty, express or implied, as to its usefulness for any purpose.
// //
// BACKGROUND: // BACKGROUND:
// When I first received an ultrasonic sensor I was not happy with how poorly // When I first received an ultrasonic sensor I was not happy with how poorly
// it worked. Quickly I realized the problem wasn't the sensor, it was the // it worked. Quickly I realized the problem wasn't the sensor, it was the
// available ping and ultrasonic libraries causing the problem. The NewPing // available ping and ultrasonic libraries causing the problem. The NewPing
// library totally fixes these problems, adds many new features, and breaths // library totally fixes these problems, adds many new features, and breaths
// new life into these very affordable distance sensors. // new life into these very affordable distance sensors.
// //
// FEATURES: // FEATURES:
// * Works with many different ultrasonic sensor models: SR04, SRF05, SRF06, DYP-ME007 & Parallax PING)))™. // * Works with many different ultrasonic sensor models: SR04, SRF05, SRF06, DYP-ME007 & Parallax PING)))™.
// * Interface with all but the SRF06 sensor using only one Arduino pin. // * Interface with all but the SRF06 sensor using only one Arduino pin.
// * Doesn't lag for a full second if no ping/echo is received. // * Doesn't lag for a full second if no ping/echo is received.
// * Ping sensors consistently and reliably at up to 30 times per second. // * Ping sensors consistently and reliably at up to 30 times per second.
// * Timer interrupt method for event-driven sketches. // * Timer interrupt method for event-driven sketches.
// * Built-in digital filter method ping_median() for easy error correction. // * Built-in digital filter method ping_median() for easy error correction.
// * Uses port registers for a faster pin interface and smaller code size. // * Uses port registers for a faster pin interface and smaller code size.
// * Allows you to set a maximum distance where pings beyond that distance are read as no ping "clear". // * Allows you to set a maximum distance where pings beyond that distance are read as no ping "clear".
// * Ease of using multiple sensors (example sketch with 15 sensors). // * Ease of using multiple sensors (example sketch with 15 sensors).
// * More accurate distance calculation (cm, inches & uS). // * More accurate distance calculation (cm, inches & uS).
// * Doesn't use pulseIn, which is slow and gives incorrect results with some ultrasonic sensor models. // * Doesn't use pulseIn, which is slow and gives incorrect results with some ultrasonic sensor models.
// * Actively developed with features being added and bugs/issues addressed. // * Actively developed with features being added and bugs/issues addressed.
// //
// CONSTRUCTOR: // CONSTRUCTOR:
// NewPing sonar(trigger_pin, echo_pin [, max_cm_distance]) // NewPing sonar(trigger_pin, echo_pin [, max_cm_distance])
// trigger_pin & echo_pin - Arduino pins connected to sensor trigger and echo. // trigger_pin & echo_pin - Arduino pins connected to sensor trigger and echo.
// NOTE: To use the same Arduino pin for trigger and echo, specify the same pin for both values. // NOTE: To use the same Arduino pin for trigger and echo, specify the same pin for both values.
// max_cm_distance - [Optional] Maximum distance you wish to sense. Default=500cm. // max_cm_distance - [Optional] Maximum distance you wish to sense. Default=500cm.
// //
// SYNTAX: // SYNTAX:
// sonar.ping() - Send a ping and get the echo time (in microseconds) as a result. // sonar.ping() - Send a ping and get the echo time (in microseconds) as a result.
// sonar.ping_in() - Send a ping and get the distance in whole inches. // sonar.ping_in() - Send a ping and get the distance in whole inches.
// sonar.ping_cm() - Send a ping and get the distance in whole centimeters. // sonar.ping_cm() - Send a ping and get the distance in whole centimeters.
// sonar.ping_median(iterations) - Do multiple pings (default=5), discard out of range pings and return median in microseconds. // sonar.ping_median(iterations) - Do multiple pings (default=5), discard out of range pings and return median in microseconds.
// sonar.convert_in(echoTime) - Convert echoTime from microseconds to inches (rounds to nearest inch). // sonar.convert_in(echoTime) - Convert echoTime from microseconds to inches (rounds to nearest inch).
// sonar.convert_cm(echoTime) - Convert echoTime from microseconds to centimeters (rounds to nearest cm). // sonar.convert_cm(echoTime) - Convert echoTime from microseconds to centimeters (rounds to nearest cm).
// sonar.ping_timer(function) - Send a ping and call function to test if ping is complete. // sonar.ping_timer(function) - Send a ping and call function to test if ping is complete.
// sonar.check_timer() - Check if ping has returned within the set distance limit. // sonar.check_timer() - Check if ping has returned within the set distance limit.
// NewPing::timer_us(frequency, function) - Call function every frequency microseconds. // NewPing::timer_us(frequency, function) - Call function every frequency microseconds.
// NewPing::timer_ms(frequency, function) - Call function every frequency milliseconds. // NewPing::timer_ms(frequency, function) - Call function every frequency milliseconds.
// NewPing::timer_stop() - Stop the timer. // NewPing::timer_stop() - Stop the timer.
// //
// HISTORY: // HISTORY:
// 08/15/2012 v1.5 - Added ping_median() method which does a user specified // 08/15/2012 v1.5 - Added ping_median() method which does a user specified
// number of pings (default=5) and returns the median ping in microseconds // number of pings (default=5) and returns the median ping in microseconds
// (out of range pings ignored). This is a very effective digital filter. // (out of range pings ignored). This is a very effective digital filter.
// Optimized for smaller compiled size (even smaller than skteches that // Optimized for smaller compiled size (even smaller than skteches that
// don't use a library). // don't use a library).
// //
// 07/14/2012 v1.4 - Added support for the Parallax PING)))™ sensor. Interface // 07/14/2012 v1.4 - Added support for the Parallax PING)))™ sensor. Interface
// with all but the SRF06 sensor using only one Arduino pin. You can also // with all but the SRF06 sensor using only one Arduino pin. You can also
// interface with the SRF06 using one pin if you install a 0.1uf capacitor // interface with the SRF06 using one pin if you install a 0.1uf capacitor
// on the trigger and echo pins of the sensor then tie the trigger pin to // on the trigger and echo pins of the sensor then tie the trigger pin to
// the Arduino pin (doesn't work with Teensy). To use the same Arduino pin // the Arduino pin (doesn't work with Teensy). To use the same Arduino pin
// for trigger and echo, specify the same pin for both values. Various bug // for trigger and echo, specify the same pin for both values. Various bug
// fixes. // fixes.
// //
// 06/08/2012 v1.3 - Big feature addition, event-driven ping! Uses Timer2 // 06/08/2012 v1.3 - Big feature addition, event-driven ping! Uses Timer2
// interrupt, so be mindful of PWM or timing conflicts messing with Timer2 // interrupt, so be mindful of PWM or timing conflicts messing with Timer2
// may cause (namely PWM on pins 3 & 11 on Arduino, PWM on pins 9 and 10 on // may cause (namely PWM on pins 3 & 11 on Arduino, PWM on pins 9 and 10 on
// Mega, and Tone library). Simple to use timer interrupt functions you can // Mega, and Tone library). Simple to use timer interrupt functions you can
// use in your sketches totaly unrelated to ultrasonic sensors (don't use if // use in your sketches totaly unrelated to ultrasonic sensors (don't use if
// you're also using NewPing's ping_timer because both use Timer2 interrupts). // you're also using NewPing's ping_timer because both use Timer2 interrupts).
// Loop counting ping method deleted in favor of timing ping method after // Loop counting ping method deleted in favor of timing ping method after
// inconsistant results kept surfacing with the loop timing ping method. // inconsistant results kept surfacing with the loop timing ping method.
// Conversion to cm and inches now rounds to the nearest cm or inch. Code // Conversion to cm and inches now rounds to the nearest cm or inch. Code
// optimized to save program space and fixed a couple minor bugs here and // optimized to save program space and fixed a couple minor bugs here and
// there. Many new comments added as well as line spacing to group code // there. Many new comments added as well as line spacing to group code
// sections for better source readability. // sections for better source readability.
// //
// 05/25/2012 v1.2 - Lots of code clean-up thanks to Adruino Forum members. // 05/25/2012 v1.2 - Lots of code clean-up thanks to Adruino Forum members.
// Rebuilt the ping timing code from scratch, ditched the pulseIn code as it // Rebuilt the ping timing code from scratch, ditched the pulseIn code as it
// doesn't give correct results (at least with ping sensors). The NewPing // doesn't give correct results (at least with ping sensors). The NewPing
// library is now VERY accurate and the code was simplified as a bonus. // library is now VERY accurate and the code was simplified as a bonus.
// Smaller and faster code as well. Fixed some issues with very close ping // Smaller and faster code as well. Fixed some issues with very close ping
// results when converting to inches. All functions now return 0 only when // results when converting to inches. All functions now return 0 only when
// there's no ping echo (out of range) and a positive value for a successful // there's no ping echo (out of range) and a positive value for a successful
// ping. This can effectively be used to detect if something is out of range // ping. This can effectively be used to detect if something is out of range
// or in-range and at what distance. Now compatible with Arduino 0023. // or in-range and at what distance. Now compatible with Arduino 0023.
// //
// 05/16/2012 v1.1 - Changed all I/O functions to use low-level port registers // 05/16/2012 v1.1 - Changed all I/O functions to use low-level port registers
// for ultra-fast and lean code (saves from 174 to 394 bytes). Tested on both // for ultra-fast and lean code (saves from 174 to 394 bytes). Tested on both
// the Arduino Uno and Teensy 2.0 but should work on all Arduino-based // the Arduino Uno and Teensy 2.0 but should work on all Arduino-based
// platforms because it calls standard functions to retrieve port registers // platforms because it calls standard functions to retrieve port registers
// and bit masks. Also made a couple minor fixes to defines. // and bit masks. Also made a couple minor fixes to defines.
// //
// 05/15/2012 v1.0 - Initial release. // 05/15/2012 v1.0 - Initial release.
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
#ifndef NewPing_h #ifndef NewPing_h
#define NewPing_h #define NewPing_h
#if defined(ARDUINO) && ARDUINO >= 100 #if defined(ARDUINO) && ARDUINO >= 100
#include <Arduino.h> #include <Arduino.h>
#else #else
#include <WProgram.h> #include <WProgram.h>
#include <pins_arduino.h> #include <pins_arduino.h>
#endif #endif
#include <avr/io.h> #include <avr/io.h>
#include <avr/interrupt.h> #include <avr/interrupt.h>
// Shoudln't need to changed these values unless you have a specific need to do so. // Shoudln't need to changed these values unless you have a specific need to do so.
#define MAX_SENSOR_DISTANCE 500 // Maximum sensor distance can be as high as 500cm, no reason to wait for ping longer than sound takes to travel this distance and back. #define MAX_SENSOR_DISTANCE 500 // Maximum sensor distance can be as high as 500cm, no reason to wait for ping longer than sound takes to travel this distance and back.
#define US_ROUNDTRIP_IN 146 // Microseconds (uS) it takes sound to travel round-trip 1 inch (2 inches total), uses integer to save compiled code space. #define US_ROUNDTRIP_IN 146 // Microseconds (uS) it takes sound to travel round-trip 1 inch (2 inches total), uses integer to save compiled code space.
#define US_ROUNDTRIP_CM 57 // Microseconds (uS) it takes sound to travel round-trip 1cm (2cm total), uses integer to save compiled code space. #define US_ROUNDTRIP_CM 57 // Microseconds (uS) it takes sound to travel round-trip 1cm (2cm total), uses integer to save compiled code space.
#define DISABLE_ONE_PIN false // Set to "true" to save up to 26 bytes of compiled code space if you're not using one pin sensor connections. #define DISABLE_ONE_PIN false // Set to "true" to save up to 26 bytes of compiled code space if you're not using one pin sensor connections.
// Probably shoudln't change these values unless you really know what you're doing. // Probably shoudln't change these values unless you really know what you're doing.
#define NO_ECHO 0 // Value returned if there's no ping echo within the specified MAX_SENSOR_DISTANCE or max_cm_distance. #define NO_ECHO 0 // Value returned if there's no ping echo within the specified MAX_SENSOR_DISTANCE or max_cm_distance.
#define MAX_SENSOR_DELAY 18000 // Maximum uS it takes for sensor to start the ping (SRF06 is the highest measured, just under 18ms). #define MAX_SENSOR_DELAY 18000 // Maximum uS it takes for sensor to start the ping (SRF06 is the highest measured, just under 18ms).
#define ECHO_TIMER_FREQ 24 // Frequency to check for a ping echo (every 24uS is about 0.4cm accuracy). #define ECHO_TIMER_FREQ 24 // Frequency to check for a ping echo (every 24uS is about 0.4cm accuracy).
#define PING_MEDIAN_DELAY 29 // Millisecond delay between pings in the ping_median method. #define PING_MEDIAN_DELAY 29 // Millisecond delay between pings in the ping_median method.
// Conversion from uS to distance (round result to nearest cm or inch). // Conversion from uS to distance (round result to nearest cm or inch).
#define NewPingConvert(echoTime, conversionFactor) (max((echoTime + conversionFactor / 2) / conversionFactor, (echoTime ? 1 : 0))) #define NewPingConvert(echoTime, conversionFactor) (max((echoTime + conversionFactor / 2) / conversionFactor, (echoTime ? 1 : 0)))
class NewPing { class NewPing {
public: public:
NewPing(uint8_t trigger_pin, uint8_t echo_pin, int max_cm_distance = MAX_SENSOR_DISTANCE); NewPing(uint8_t trigger_pin, uint8_t echo_pin, int max_cm_distance = MAX_SENSOR_DISTANCE);
unsigned int ping(); unsigned int ping();
unsigned int ping_in(); unsigned int ping_in();
unsigned int ping_cm(); unsigned int ping_cm();
unsigned int ping_median(uint8_t it = 5); unsigned int ping_median(uint8_t it = 5);
unsigned int convert_in(unsigned int echoTime); unsigned int convert_in(unsigned int echoTime);
unsigned int convert_cm(unsigned int echoTime); unsigned int convert_cm(unsigned int echoTime);
void ping_timer(void (*userFunc)(void)); void ping_timer(void (*userFunc)(void));
boolean check_timer(); boolean check_timer();
unsigned long ping_result; unsigned long ping_result;
static void timer_us(unsigned int frequency, void (*userFunc)(void)); static void timer_us(unsigned int frequency, void (*userFunc)(void));
static void timer_ms(unsigned long frequency, void (*userFunc)(void)); static void timer_ms(unsigned long frequency, void (*userFunc)(void));
static void timer_stop(); static void timer_stop();
private: private:
boolean ping_trigger(); boolean ping_trigger();
boolean ping_wait_timer(); boolean ping_wait_timer();
uint8_t _triggerBit; uint8_t _triggerBit;
uint8_t _echoBit; uint8_t _echoBit;
volatile uint8_t *_triggerOutput; volatile uint8_t *_triggerOutput;
volatile uint8_t *_triggerMode; volatile uint8_t *_triggerMode;
volatile uint8_t *_echoInput; volatile uint8_t *_echoInput;
unsigned int _maxEchoTime; unsigned int _maxEchoTime;
unsigned long _max_time; unsigned long _max_time;
static void timer_setup(); static void timer_setup();
static void timer_ms_cntdwn(); static void timer_ms_cntdwn();
}; };
#endif #endif
@@ -1,74 +1,74 @@
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// This example code was used to successfully communicate with 15 ultrasonic sensors. You can adjust // This example code was used to successfully communicate with 15 ultrasonic sensors. You can adjust
// the number of sensors in your project by changing SONAR_NUM and the number of NewPing objects in the // the number of sensors in your project by changing SONAR_NUM and the number of NewPing objects in the
// "sonar" array. You also need to change the pins for each sensor for the NewPing objects. Each sensor // "sonar" array. You also need to change the pins for each sensor for the NewPing objects. Each sensor
// is pinged at 33ms intervals. So, one cycle of all sensors takes 495ms (33 * 15 = 495ms). The results // is pinged at 33ms intervals. So, one cycle of all sensors takes 495ms (33 * 15 = 495ms). The results
// are sent to the "oneSensorCycle" function which currently just displays the distance data. Your project // are sent to the "oneSensorCycle" function which currently just displays the distance data. Your project
// would normally process the sensor results in this function (for example, decide if a robot needs to // would normally process the sensor results in this function (for example, decide if a robot needs to
// turn and call the turn function). Keep in mind this example is event-driven. Your complete sketch needs // turn and call the turn function). Keep in mind this example is event-driven. Your complete sketch needs
// to be written so there's no "delay" commands and the loop() cycles at faster than a 33ms rate. If other // to be written so there's no "delay" commands and the loop() cycles at faster than a 33ms rate. If other
// processes take longer than 33ms, you'll need to increase PING_INTERVAL so it doesn't get behind. // processes take longer than 33ms, you'll need to increase PING_INTERVAL so it doesn't get behind.
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
#include <NewPing.h> #include <NewPing.h>
#define SONAR_NUM 15 // Number or sensors. #define SONAR_NUM 15 // Number or sensors.
#define MAX_DISTANCE 200 // Maximum distance (in cm) to ping. #define MAX_DISTANCE 200 // Maximum distance (in cm) to ping.
#define PING_INTERVAL 33 // Milliseconds between sensor pings (29ms is about the min to avoid cross-sensor echo). #define PING_INTERVAL 33 // Milliseconds between sensor pings (29ms is about the min to avoid cross-sensor echo).
unsigned long pingTimer[SONAR_NUM]; // Holds the times when the next ping should happen for each sensor. unsigned long pingTimer[SONAR_NUM]; // Holds the times when the next ping should happen for each sensor.
unsigned int cm[SONAR_NUM]; // Where the ping distances are stored. unsigned int cm[SONAR_NUM]; // Where the ping distances are stored.
uint8_t currentSensor = 0; // Keeps track of which sensor is active. uint8_t currentSensor = 0; // Keeps track of which sensor is active.
NewPing sonar[SONAR_NUM] = { // Sensor object array. NewPing sonar[SONAR_NUM] = { // Sensor object array.
NewPing(41, 42, MAX_DISTANCE), // Each sensor's trigger pin, echo pin, and max distance to ping. NewPing(41, 42, MAX_DISTANCE), // Each sensor's trigger pin, echo pin, and max distance to ping.
NewPing(43, 44, MAX_DISTANCE), NewPing(43, 44, MAX_DISTANCE),
NewPing(45, 20, MAX_DISTANCE), NewPing(45, 20, MAX_DISTANCE),
NewPing(21, 22, MAX_DISTANCE), NewPing(21, 22, MAX_DISTANCE),
NewPing(23, 24, MAX_DISTANCE), NewPing(23, 24, MAX_DISTANCE),
NewPing(25, 26, MAX_DISTANCE), NewPing(25, 26, MAX_DISTANCE),
NewPing(27, 28, MAX_DISTANCE), NewPing(27, 28, MAX_DISTANCE),
NewPing(29, 30, MAX_DISTANCE), NewPing(29, 30, MAX_DISTANCE),
NewPing(31, 32, MAX_DISTANCE), NewPing(31, 32, MAX_DISTANCE),
NewPing(34, 33, MAX_DISTANCE), NewPing(34, 33, MAX_DISTANCE),
NewPing(35, 36, MAX_DISTANCE), NewPing(35, 36, MAX_DISTANCE),
NewPing(37, 38, MAX_DISTANCE), NewPing(37, 38, MAX_DISTANCE),
NewPing(39, 40, MAX_DISTANCE), NewPing(39, 40, MAX_DISTANCE),
NewPing(50, 51, MAX_DISTANCE), NewPing(50, 51, MAX_DISTANCE),
NewPing(52, 53, MAX_DISTANCE) NewPing(52, 53, MAX_DISTANCE)
}; };
void setup() { void setup() {
Serial.begin(115200); Serial.begin(115200);
pingTimer[0] = millis() + 75; // First ping starts at 75ms, gives time for the Arduino to chill before starting. pingTimer[0] = millis() + 75; // First ping starts at 75ms, gives time for the Arduino to chill before starting.
for (uint8_t i = 1; i < SONAR_NUM; i++) // Set the starting time for each sensor. for (uint8_t i = 1; i < SONAR_NUM; i++) // Set the starting time for each sensor.
pingTimer[i] = pingTimer[i - 1] + PING_INTERVAL; pingTimer[i] = pingTimer[i - 1] + PING_INTERVAL;
} }
void loop() { void loop() {
for (uint8_t i = 0; i < SONAR_NUM; i++) { // Loop through all the sensors. for (uint8_t i = 0; i < SONAR_NUM; i++) { // Loop through all the sensors.
if (millis() >= pingTimer[i]) { // Is it this sensor's time to ping? if (millis() >= pingTimer[i]) { // Is it this sensor's time to ping?
pingTimer[i] += PING_INTERVAL * SONAR_NUM; // Set next time this sensor will be pinged. pingTimer[i] += PING_INTERVAL * SONAR_NUM; // Set next time this sensor will be pinged.
if (i == 0 && currentSensor == SONAR_NUM - 1) oneSensorCycle(); // Sensor ping cycle complete, do something with the results. if (i == 0 && currentSensor == SONAR_NUM - 1) oneSensorCycle(); // Sensor ping cycle complete, do something with the results.
sonar[currentSensor].timer_stop(); // Make sure previous timer is canceled before starting a new ping (insurance). sonar[currentSensor].timer_stop(); // Make sure previous timer is canceled before starting a new ping (insurance).
currentSensor = i; // Sensor being accessed. currentSensor = i; // Sensor being accessed.
cm[currentSensor] = 0; // Make distance zero in case there's no ping echo for this sensor. cm[currentSensor] = 0; // Make distance zero in case there's no ping echo for this sensor.
sonar[currentSensor].ping_timer(echoCheck); // Do the ping (processing continues, interrupt will call echoCheck to look for echo). sonar[currentSensor].ping_timer(echoCheck); // Do the ping (processing continues, interrupt will call echoCheck to look for echo).
} }
} }
// The rest of your code would go here. // The rest of your code would go here.
} }
void echoCheck() { // If ping received, set the sensor distance to array. void echoCheck() { // If ping received, set the sensor distance to array.
if (sonar[currentSensor].check_timer()) if (sonar[currentSensor].check_timer())
cm[currentSensor] = sonar[currentSensor].ping_result / US_ROUNDTRIP_CM; cm[currentSensor] = sonar[currentSensor].ping_result / US_ROUNDTRIP_CM;
} }
void oneSensorCycle() { // Sensor ping cycle complete, do something with the results. void oneSensorCycle() { // Sensor ping cycle complete, do something with the results.
for (uint8_t i = 0; i < SONAR_NUM; i++) { for (uint8_t i = 0; i < SONAR_NUM; i++) {
Serial.print(i); Serial.print(i);
Serial.print("="); Serial.print("=");
Serial.print(cm[i]); Serial.print(cm[i]);
Serial.print("cm "); Serial.print("cm ");
} }
Serial.println(); Serial.println();
} }
@@ -20,4 +20,4 @@ void loop() {
Serial.print("Ping: "); Serial.print("Ping: ");
Serial.print(uS / US_ROUNDTRIP_CM); // Convert ping time to distance in cm and print result (0 = outside set distance range) Serial.print(uS / US_ROUNDTRIP_CM); // Convert ping time to distance in cm and print result (0 = outside set distance range)
Serial.println("cm"); Serial.println("cm");
} }
@@ -1,25 +1,25 @@
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// While the NewPing library's primary goal is to interface with ultrasonic sensors, interfacing with // While the NewPing library's primary goal is to interface with ultrasonic sensors, interfacing with
// the Timer2 interrupt was a result of creating an interrupt-based ping method. Since these Timer2 // the Timer2 interrupt was a result of creating an interrupt-based ping method. Since these Timer2
// interrupt methods were built, the library may as well provide the functionality to use these methods // interrupt methods were built, the library may as well provide the functionality to use these methods
// in your sketches. This shows how simple it is (no ultrasonic sensor required). Keep in mind that // in your sketches. This shows how simple it is (no ultrasonic sensor required). Keep in mind that
// these methods use Timer2, as does NewPing's ping_timer method for using ultrasonic sensors. You // these methods use Timer2, as does NewPing's ping_timer method for using ultrasonic sensors. You
// can't use ping_timer at the same time you're using timer_ms or timer_us as all use the same timer. // can't use ping_timer at the same time you're using timer_ms or timer_us as all use the same timer.
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
#include <NewPing.h> #include <NewPing.h>
#define LED_PIN 13 // Pin with LED attached. #define LED_PIN 13 // Pin with LED attached.
void setup() { void setup() {
pinMode(LED_PIN, OUTPUT); pinMode(LED_PIN, OUTPUT);
NewPing::timer_ms(500, toggleLED); // Create a Timer2 interrupt that calls toggleLED in your sketch once every 500 milliseconds. NewPing::timer_ms(500, toggleLED); // Create a Timer2 interrupt that calls toggleLED in your sketch once every 500 milliseconds.
} }
void loop() { void loop() {
// Do anything here, the Timer2 interrupt will take care of the flashing LED without your intervention. // Do anything here, the Timer2 interrupt will take care of the flashing LED without your intervention.
} }
void toggleLED() { void toggleLED() {
digitalWrite(LED_PIN, !digitalRead(LED_PIN)); // Toggle the LED. digitalWrite(LED_PIN, !digitalRead(LED_PIN)); // Toggle the LED.
} }
+29 -29
View File
@@ -1,29 +1,29 @@
################################### ###################################
# Syntax Coloring Map For NewPing # Syntax Coloring Map For NewPing
################################### ###################################
################################### ###################################
# Datatypes (KEYWORD1) # Datatypes (KEYWORD1)
################################### ###################################
NewPing KEYWORD1 NewPing KEYWORD1
################################### ###################################
# Methods and Functions (KEYWORD2) # Methods and Functions (KEYWORD2)
################################### ###################################
ping KEYWORD2 ping KEYWORD2
ping_in KEYWORD2 ping_in KEYWORD2
ping_cm KEYWORD2 ping_cm KEYWORD2
ping_median KEYWORD2 ping_median KEYWORD2
ping_timer KEYWORD2 ping_timer KEYWORD2
check_timer KEYWORD2 check_timer KEYWORD2
timer_us KEYWORD2 timer_us KEYWORD2
timer_ms KEYWORD2 timer_ms KEYWORD2
timer_stop KEYWORD2 timer_stop KEYWORD2
convert_in KEYWORD2 convert_in KEYWORD2
convert_cm KEYWORD2 convert_cm KEYWORD2
################################### ###################################
# Constants (LITERAL1) # Constants (LITERAL1)
################################### ###################################
+318 -318
View File
@@ -1,318 +1,318 @@
/* /*
* NewRemoteSwitch library v1.1.0 (20130601) made by Randy Simons http://randysimons.nl/ * NewRemoteSwitch library v1.1.0 (20130601) made by Randy Simons http://randysimons.nl/
* See NewRemoteReceiver.h for details. * See NewRemoteReceiver.h for details.
* *
* License: GPLv3. See license.txt * License: GPLv3. See license.txt
*/ */
#include "NewRemoteReceiver.h" #include "NewRemoteReceiver.h"
/************ /************
* NewRemoteReceiver * NewRemoteReceiver
Protocol. (Copied from Wieltje, http://www.circuitsonline.net/forum/view/message/1181410#1181410, Protocol. (Copied from Wieltje, http://www.circuitsonline.net/forum/view/message/1181410#1181410,
but with slightly different timings, as measured on my device.) but with slightly different timings, as measured on my device.)
_ _ _ _
'0': | |_| |_____ (T,T,T,5T) '0': | |_| |_____ (T,T,T,5T)
_ _ _ _
'1': | |_____| |_ (T,5T,T,T) '1': | |_____| |_ (T,5T,T,T)
_ _ _ _
dim: | |_| |_ (T,T,T,T) dim: | |_| |_ (T,T,T,T)
T = short period of ~260µs. However, this code tries T = short period of ~260µs. However, this code tries
to figure out the correct period to figure out the correct period
A full frame looks like this: A full frame looks like this:
- start pulse: 1T high, 10.44T low - start pulse: 1T high, 10.44T low
- 26 bit: Address - 26 bit: Address
- 1 bit: group bit - 1 bit: group bit
- 1 bit: on/off/[dim] - 1 bit: on/off/[dim]
- 4 bit: unit - 4 bit: unit
- [4 bit: dim level. Only present of [dim] is chosen] - [4 bit: dim level. Only present of [dim] is chosen]
- stop pulse: 1T high, 40T low - stop pulse: 1T high, 40T low
************/ ************/
int8_t NewRemoteReceiver::_interrupt; int8_t NewRemoteReceiver::_interrupt;
volatile short NewRemoteReceiver::_state; volatile short NewRemoteReceiver::_state;
byte NewRemoteReceiver::_minRepeats; byte NewRemoteReceiver::_minRepeats;
NewRemoteReceiverCallBack NewRemoteReceiver::_callback; NewRemoteReceiverCallBack NewRemoteReceiver::_callback;
boolean NewRemoteReceiver::_inCallback = false; boolean NewRemoteReceiver::_inCallback = false;
boolean NewRemoteReceiver::_enabled = false; boolean NewRemoteReceiver::_enabled = false;
void NewRemoteReceiver::init(int8_t interrupt, byte minRepeats, NewRemoteReceiverCallBack callback) { void NewRemoteReceiver::init(int8_t interrupt, byte minRepeats, NewRemoteReceiverCallBack callback) {
_interrupt = interrupt; _interrupt = interrupt;
_minRepeats = minRepeats; _minRepeats = minRepeats;
_callback = callback; _callback = callback;
enable(); enable();
if (_interrupt >= 0) { if (_interrupt >= 0) {
attachInterrupt(_interrupt, interruptHandler, CHANGE); attachInterrupt(_interrupt, interruptHandler, CHANGE);
} }
} }
void NewRemoteReceiver::enable() { void NewRemoteReceiver::enable() {
_state = -1; _state = -1;
_enabled = true; _enabled = true;
} }
void NewRemoteReceiver::disable() { void NewRemoteReceiver::disable() {
_enabled = false; _enabled = false;
} }
void NewRemoteReceiver::deinit() { void NewRemoteReceiver::deinit() {
_enabled = false; _enabled = false;
if (_interrupt >= 0) { if (_interrupt >= 0) {
detachInterrupt(_interrupt); detachInterrupt(_interrupt);
} }
} }
void NewRemoteReceiver::interruptHandler() { void NewRemoteReceiver::interruptHandler() {
// This method is written as compact code to keep it fast. While breaking up this method into more // This method is written as compact code to keep it fast. While breaking up this method into more
// methods would certainly increase the readability, it would also be much slower to execute. // methods would certainly increase the readability, it would also be much slower to execute.
// Making calls to other methods is quite expensive on AVR. As These interrupt handlers are called // Making calls to other methods is quite expensive on AVR. As These interrupt handlers are called
// many times a second, calling other methods should be kept to a minimum. // many times a second, calling other methods should be kept to a minimum.
if (!_enabled) { if (!_enabled) {
return; return;
} }
static byte receivedBit; // Contains "bit" currently receiving static byte receivedBit; // Contains "bit" currently receiving
static NewRemoteCode receivedCode; // Contains received code static NewRemoteCode receivedCode; // Contains received code
static NewRemoteCode previousCode; // Contains previous received code static NewRemoteCode previousCode; // Contains previous received code
static byte repeats = 0; // The number of times the an identical code is received in a row. static byte repeats = 0; // The number of times the an identical code is received in a row.
static unsigned long edgeTimeStamp[3] = {0, }; // Timestamp of edges static unsigned long edgeTimeStamp[3] = {0, }; // Timestamp of edges
static unsigned int min1Period, max1Period, min5Period, max5Period; static unsigned int min1Period, max1Period, min5Period, max5Period;
static bool skip; static bool skip;
// Filter out too short pulses. This method works as a low pass filter. // Filter out too short pulses. This method works as a low pass filter.
edgeTimeStamp[1] = edgeTimeStamp[2]; edgeTimeStamp[1] = edgeTimeStamp[2];
edgeTimeStamp[2] = micros(); edgeTimeStamp[2] = micros();
if (skip) { if (skip) {
skip = false; skip = false;
return; return;
} }
if (_state >= 0 && edgeTimeStamp[2]-edgeTimeStamp[1] < min1Period) { if (_state >= 0 && edgeTimeStamp[2]-edgeTimeStamp[1] < min1Period) {
// Last edge was too short. // Last edge was too short.
// Skip this edge, and the next too. // Skip this edge, and the next too.
skip = true; skip = true;
return; return;
} }
unsigned int duration = edgeTimeStamp[1] - edgeTimeStamp[0]; unsigned int duration = edgeTimeStamp[1] - edgeTimeStamp[0];
edgeTimeStamp[0] = edgeTimeStamp[1]; edgeTimeStamp[0] = edgeTimeStamp[1];
// Note that if state>=0, duration is always >= 1 period. // Note that if state>=0, duration is always >= 1 period.
if (_state == -1) { if (_state == -1) {
// wait for the long low part of a stop bit. // wait for the long low part of a stop bit.
// Stopbit: 1T high, 40T low // Stopbit: 1T high, 40T low
// By default 1T is 260µs, but for maximum compatibility go as low as 120µs // By default 1T is 260µs, but for maximum compatibility go as low as 120µs
if (duration > 4800) { // =40*120µs, minimal time between two edges before decoding starts. if (duration > 4800) { // =40*120µs, minimal time between two edges before decoding starts.
// Sync signal received.. Preparing for decoding // Sync signal received.. Preparing for decoding
repeats = 0; repeats = 0;
receivedCode.period = duration / 40; // Measured signal is 40T, so 1T (period) is measured signal / 40. receivedCode.period = duration / 40; // Measured signal is 40T, so 1T (period) is measured signal / 40.
// Allow for large error-margin. ElCheapo-hardware :( // Allow for large error-margin. ElCheapo-hardware :(
min1Period = receivedCode.period * 3 / 10; // Lower limit for 1 period is 0.3 times measured period; high signals can "linger" a bit sometimes, making low signals quite short. min1Period = receivedCode.period * 3 / 10; // Lower limit for 1 period is 0.3 times measured period; high signals can "linger" a bit sometimes, making low signals quite short.
max1Period = receivedCode.period * 3; // Upper limit for 1 period is 3 times measured period max1Period = receivedCode.period * 3; // Upper limit for 1 period is 3 times measured period
min5Period = receivedCode.period * 3; // Lower limit for 5 periods is 3 times measured period min5Period = receivedCode.period * 3; // Lower limit for 5 periods is 3 times measured period
max5Period = receivedCode.period * 8; // Upper limit for 5 periods is 8 times measured period max5Period = receivedCode.period * 8; // Upper limit for 5 periods is 8 times measured period
} }
else { else {
return; return;
} }
} else if (_state == 0) { // Verify start bit part 1 of 2 } else if (_state == 0) { // Verify start bit part 1 of 2
// Duration must be ~1T // Duration must be ~1T
if (duration > max1Period) { if (duration > max1Period) {
_state = -1; _state = -1;
return; return;
} }
// Start-bit passed. Do some clean-up. // Start-bit passed. Do some clean-up.
receivedCode.address = receivedCode.unit = receivedCode.dimLevel = 0; receivedCode.address = receivedCode.unit = receivedCode.dimLevel = 0;
} else if (_state == 1) { // Verify start bit part 2 of 2 } else if (_state == 1) { // Verify start bit part 2 of 2
// Duration must be ~10.44T // Duration must be ~10.44T
if (duration < 7 * receivedCode.period || duration > 15 * receivedCode.period) { if (duration < 7 * receivedCode.period || duration > 15 * receivedCode.period) {
_state = -1; _state = -1;
return; return;
} }
} else if (_state < 148) { // state 146 is first edge of stop-sequence. All bits before that adhere to default protocol, with exception of dim-bit } else if (_state < 148) { // state 146 is first edge of stop-sequence. All bits before that adhere to default protocol, with exception of dim-bit
receivedBit <<= 1; receivedBit <<= 1;
// One bit consists out of 4 bit parts. // One bit consists out of 4 bit parts.
// bit part durations can ONLY be 1 or 5 periods. // bit part durations can ONLY be 1 or 5 periods.
if (duration <= max1Period) { if (duration <= max1Period) {
receivedBit &= B1110; // Clear LSB of receivedBit receivedBit &= B1110; // Clear LSB of receivedBit
} else if (duration >= min5Period && duration <= max5Period) { } else if (duration >= min5Period && duration <= max5Period) {
receivedBit |= B1; // Set LSB of receivedBit receivedBit |= B1; // Set LSB of receivedBit
} else if ( } else if (
// Check if duration matches the second part of stopbit (duration must be ~40T), and ... // Check if duration matches the second part of stopbit (duration must be ~40T), and ...
(duration >= 20 * receivedCode.period && duration <= 80 * receivedCode.period) && (duration >= 20 * receivedCode.period && duration <= 80 * receivedCode.period) &&
// if first part op stopbit was a short signal (short signal yielded a 0 as second bit in receivedBit), and ... // if first part op stopbit was a short signal (short signal yielded a 0 as second bit in receivedBit), and ...
((receivedBit & B10) == B00) && ((receivedBit & B10) == B00) &&
// we are in a state in which a stopbit is actually valid, only then ... // we are in a state in which a stopbit is actually valid, only then ...
(_state == 147 || _state == 131) ) { (_state == 147 || _state == 131) ) {
// If a dim-level was present... // If a dim-level was present...
if (_state == 147) { if (_state == 147) {
// ... test if it was an "on" signal ... // ... test if it was an "on" signal ...
if (receivedCode.switchType == NewRemoteCode::on) { if (receivedCode.switchType == NewRemoteCode::on) {
// ... set the appropriate switch type // ... set the appropriate switch type
receivedCode.switchType = NewRemoteCode::on_with_dim; receivedCode.switchType = NewRemoteCode::on_with_dim;
} else { } else {
// ... otherwise it was wrong (e.g. off-signal with dim) // ... otherwise it was wrong (e.g. off-signal with dim)
_state = -1; _state = -1;
return; return;
} }
} }
// a valid signal was found! // a valid signal was found!
if ( if (
receivedCode.address != previousCode.address || receivedCode.address != previousCode.address ||
receivedCode.unit != previousCode.unit || receivedCode.unit != previousCode.unit ||
receivedCode.dimLevel != previousCode.dimLevel || receivedCode.dimLevel != previousCode.dimLevel ||
receivedCode.groupBit != previousCode.groupBit || receivedCode.groupBit != previousCode.groupBit ||
receivedCode.switchType != previousCode.switchType receivedCode.switchType != previousCode.switchType
) { // memcmp isn't deemed safe ) { // memcmp isn't deemed safe
repeats=0; repeats=0;
previousCode = receivedCode; previousCode = receivedCode;
} }
repeats++; repeats++;
if (repeats>=_minRepeats) { if (repeats>=_minRepeats) {
if (!_inCallback) { if (!_inCallback) {
_inCallback = true; _inCallback = true;
(_callback)(receivedCode); (_callback)(receivedCode);
_inCallback = false; _inCallback = false;
} }
// Reset after callback. // Reset after callback.
_state=-1; _state=-1;
return; return;
} }
// Reset for next round // Reset for next round
_state=0; // no need to wait for another sync-bit! _state=0; // no need to wait for another sync-bit!
return; return;
} }
else { // Otherwise the entire sequence is invalid else { // Otherwise the entire sequence is invalid
_state = -1; _state = -1;
return; return;
} }
if (_state % 4 == 1) { // Last bit part? Note: this is the short version of "if ( (_state-2) % 4 == 3 )" if (_state % 4 == 1) { // Last bit part? Note: this is the short version of "if ( (_state-2) % 4 == 3 )"
// There are 3 valid options for receivedBit: // There are 3 valid options for receivedBit:
// 0, indicated by short short short long == B0001. // 0, indicated by short short short long == B0001.
// 1, short long shot short == B0100. // 1, short long shot short == B0100.
// dim, short shot short shot == B0000. // dim, short shot short shot == B0000.
// Everything else: inconsistent data, trash the whole sequence. // Everything else: inconsistent data, trash the whole sequence.
if (_state < 106) { if (_state < 106) {
// States 2 - 105 are address bit states // States 2 - 105 are address bit states
receivedCode.address <<= 1; receivedCode.address <<= 1;
// Decode bit. Only 4 LSB's of receivedBit are used; trim the rest. // Decode bit. Only 4 LSB's of receivedBit are used; trim the rest.
switch (receivedBit & B1111) { switch (receivedBit & B1111) {
case B0001: // Bit "0" received. case B0001: // Bit "0" received.
// receivedCode.address |= 0; But let's not do that, as it is wasteful. // receivedCode.address |= 0; But let's not do that, as it is wasteful.
break; break;
case B0100: // Bit "1" received. case B0100: // Bit "1" received.
receivedCode.address |= 1; receivedCode.address |= 1;
break; break;
default: // Bit was invalid. Abort. default: // Bit was invalid. Abort.
_state = -1; _state = -1;
return; return;
} }
} else if (_state < 110) { } else if (_state < 110) {
// States 106 - 109 are group bit states. // States 106 - 109 are group bit states.
switch (receivedBit & B1111) { switch (receivedBit & B1111) {
case B0001: // Bit "0" received. case B0001: // Bit "0" received.
receivedCode.groupBit = false; receivedCode.groupBit = false;
break; break;
case B0100: // Bit "1" received. case B0100: // Bit "1" received.
receivedCode.groupBit = true; receivedCode.groupBit = true;
break; break;
default: // Bit was invalid. Abort. default: // Bit was invalid. Abort.
_state = -1; _state = -1;
return; return;
} }
} else if (_state < 114) { } else if (_state < 114) {
// States 110 - 113 are switch bit states. // States 110 - 113 are switch bit states.
switch (receivedBit & B1111) { switch (receivedBit & B1111) {
case B0001: // Bit "0" received. case B0001: // Bit "0" received.
receivedCode.switchType = NewRemoteCode::off; receivedCode.switchType = NewRemoteCode::off;
break; break;
case B0100: // Bit "1" received. Note: this might turn out to be a on_with_dim signal. case B0100: // Bit "1" received. Note: this might turn out to be a on_with_dim signal.
receivedCode.switchType = NewRemoteCode::on; receivedCode.switchType = NewRemoteCode::on;
break; break;
case B0000: // Bit "dim" received. case B0000: // Bit "dim" received.
receivedCode.switchType = NewRemoteCode::dim; receivedCode.switchType = NewRemoteCode::dim;
break; break;
default: // Bit was invalid. Abort. default: // Bit was invalid. Abort.
_state = -1; _state = -1;
return; return;
} }
} else if (_state < 130){ } else if (_state < 130){
// States 114 - 129 are unit bit states. // States 114 - 129 are unit bit states.
receivedCode.unit <<= 1; receivedCode.unit <<= 1;
// Decode bit. // Decode bit.
switch (receivedBit & B1111) { switch (receivedBit & B1111) {
case B0001: // Bit "0" received. case B0001: // Bit "0" received.
// receivedCode.unit |= 0; But let's not do that, as it is wasteful. // receivedCode.unit |= 0; But let's not do that, as it is wasteful.
break; break;
case B0100: // Bit "1" received. case B0100: // Bit "1" received.
receivedCode.unit |= 1; receivedCode.unit |= 1;
break; break;
default: // Bit was invalid. Abort. default: // Bit was invalid. Abort.
_state = -1; _state = -1;
return; return;
} }
} else if (_state < 146) { } else if (_state < 146) {
// States 130 - 145 are dim bit states. // States 130 - 145 are dim bit states.
// If switchType == 0 these are never present. // If switchType == 0 these are never present.
// If switchType == 2 these are always present. // If switchType == 2 these are always present.
// If switchType == 1 these are or are not present, depending on the revision of the transmitter. // If switchType == 1 these are or are not present, depending on the revision of the transmitter.
receivedCode.dimLevel <<= 1; receivedCode.dimLevel <<= 1;
// Decode bit. // Decode bit.
switch (receivedBit & B1111) { switch (receivedBit & B1111) {
case B0001: // Bit "0" received. case B0001: // Bit "0" received.
// receivedCode.dimLevel |= 0; But let's not do that, as it is wasteful. // receivedCode.dimLevel |= 0; But let's not do that, as it is wasteful.
break; break;
case B0100: // Bit "1" received. case B0100: // Bit "1" received.
receivedCode.dimLevel |= 1; receivedCode.dimLevel |= 1;
break; break;
default: // Bit was invalid. Abort. default: // Bit was invalid. Abort.
_state = -1; _state = -1;
return; return;
} }
} }
} }
} }
_state++; _state++;
return; return;
} }
boolean NewRemoteReceiver::isReceiving(int waitMillis) { boolean NewRemoteReceiver::isReceiving(int waitMillis) {
unsigned long startTime=millis(); unsigned long startTime=millis();
int waited; // Signed int! int waited; // Signed int!
do { do {
if (_state >= 34) { // Abort if a significant part of a code (start pulse + 8 bits) has been received if (_state >= 34) { // Abort if a significant part of a code (start pulse + 8 bits) has been received
return true; return true;
} }
waited = (millis()-startTime); waited = (millis()-startTime);
} while(waited>=0 && waited <= waitMillis); // Yes, clock wraps every 50 days. And then you'd have to wait for a looooong time. } while(waited>=0 && waited <= waitMillis); // Yes, clock wraps every 50 days. And then you'd have to wait for a looooong time.
return false; return false;
} }
+107 -107
View File
@@ -1,107 +1,107 @@
/* /*
* NewRemoteSwitch library v1.1.0 (20130601) made by Randy Simons http://randysimons.nl/ * NewRemoteSwitch library v1.1.0 (20130601) made by Randy Simons http://randysimons.nl/
* *
* License: GPLv3. See license.txt * License: GPLv3. See license.txt
*/ */
#ifndef NewRemoteReceiver_h #ifndef NewRemoteReceiver_h
#define NewRemoteReceiver_h #define NewRemoteReceiver_h
#include <Arduino.h> #include <Arduino.h>
struct NewRemoteCode { struct NewRemoteCode {
enum SwitchType { enum SwitchType {
off = 0, off = 0,
on = 1, on = 1,
dim = 2, dim = 2,
on_with_dim = 3 on_with_dim = 3
}; };
unsigned int period; // Detected duration in microseconds of 1T in the received signal unsigned int period; // Detected duration in microseconds of 1T in the received signal
unsigned long address; // Address of received code. [0..2^26-1] unsigned long address; // Address of received code. [0..2^26-1]
boolean groupBit; // Group bit set or not boolean groupBit; // Group bit set or not
SwitchType switchType; // off, on, dim, on_with_dim. SwitchType switchType; // off, on, dim, on_with_dim.
byte unit; // Unit code of received code [0..15] byte unit; // Unit code of received code [0..15]
byte dimLevel; // Dim level [0..15] iff switchType == 2 byte dimLevel; // Dim level [0..15] iff switchType == 2
}; };
typedef void (*NewRemoteReceiverCallBack)(NewRemoteCode); typedef void (*NewRemoteReceiverCallBack)(NewRemoteCode);
/** /**
* See RemoteSwitch for introduction. * See RemoteSwitch for introduction.
* *
* NewRemoteReceiver decodes the signal received from a 433MHz-receiver, like the "KlikAanKlikUit"-system * NewRemoteReceiver decodes the signal received from a 433MHz-receiver, like the "KlikAanKlikUit"-system
* as well as the signal sent by the RemoteSwtich class. When a correct signal is received, * as well as the signal sent by the RemoteSwtich class. When a correct signal is received,
* a user-defined callback function is called. * a user-defined callback function is called.
* *
* Note that in the callback function, the interrupts are still disabled. You can enabled them, if needed. * Note that in the callback function, the interrupts are still disabled. You can enabled them, if needed.
* A call to the callback must be finished before NewRemoteReceiver will call the callback function again, thus * A call to the callback must be finished before NewRemoteReceiver will call the callback function again, thus
* there is no re-entrant problem. * there is no re-entrant problem.
* *
* When sending your own code using NewRemoteSwich, disable() the receiver first. * When sending your own code using NewRemoteSwich, disable() the receiver first.
* *
* This is a pure static class, for simplicity and to limit memory-use. * This is a pure static class, for simplicity and to limit memory-use.
*/ */
class NewRemoteReceiver { class NewRemoteReceiver {
public: public:
/** /**
* Initializes the decoder. * Initializes the decoder.
* *
* If interrupt >= 0, init will register pin <interrupt> to this library. * If interrupt >= 0, init will register pin <interrupt> to this library.
* If interrupt < 0, no interrupt is registered. In that case, you have to call interruptHandler() * If interrupt < 0, no interrupt is registered. In that case, you have to call interruptHandler()
* yourself whenever the output of the receiver changes, or you can use InterruptChain. * yourself whenever the output of the receiver changes, or you can use InterruptChain.
* *
* @param interrupt The interrupt as is used by Arduino's attachInterrupt function. See attachInterrupt for details. * @param interrupt The interrupt as is used by Arduino's attachInterrupt function. See attachInterrupt for details.
If < 0, you must call interruptHandler() yourself. If < 0, you must call interruptHandler() yourself.
* @param minRepeats The number of times the same code must be received in a row before the callback is calles * @param minRepeats The number of times the same code must be received in a row before the callback is calles
* @param callback Pointer to a callback function, with signature void (*func)(NewRemoteCode) * @param callback Pointer to a callback function, with signature void (*func)(NewRemoteCode)
*/ */
static void init(int8_t interrupt, byte minRepeats, NewRemoteReceiverCallBack callback); static void init(int8_t interrupt, byte minRepeats, NewRemoteReceiverCallBack callback);
/** /**
* Enable decoding. No need to call enable() after init(). * Enable decoding. No need to call enable() after init().
*/ */
static void enable(); static void enable();
/** /**
* Disable decoding. You can re-enable decoding by calling enable(); * Disable decoding. You can re-enable decoding by calling enable();
*/ */
static void disable(); static void disable();
/** /**
* Deinitializes the decoder. Disables decoding and detaches the interrupt handler. If you want to * Deinitializes the decoder. Disables decoding and detaches the interrupt handler. If you want to
* re-enable decoding, call init() again. * re-enable decoding, call init() again.
*/ */
static void deinit(); static void deinit();
/** /**
* Tells wether a signal is being received. If a compatible signal is detected within the time out, isReceiving returns true. * Tells wether a signal is being received. If a compatible signal is detected within the time out, isReceiving returns true.
* Since it makes no sense to transmit while another transmitter is active, it's best to wait for isReceiving() to false. * Since it makes no sense to transmit while another transmitter is active, it's best to wait for isReceiving() to false.
* By default it waits for 150ms, in which a (relative slow) KaKu signal can be broadcasted three times. * By default it waits for 150ms, in which a (relative slow) KaKu signal can be broadcasted three times.
* *
* Note: isReceiving() depends on interrupts enabled. Thus, when disabled()'ed, or when interrupts are disabled (as is * Note: isReceiving() depends on interrupts enabled. Thus, when disabled()'ed, or when interrupts are disabled (as is
* the case in the callback), isReceiving() will not work properly. * the case in the callback), isReceiving() will not work properly.
* *
* @param waitMillis number of milliseconds to monitor for signal. * @param waitMillis number of milliseconds to monitor for signal.
* @return boolean If after waitMillis no signal was being processed, returns false. If before expiration a signal was being processed, returns true. * @return boolean If after waitMillis no signal was being processed, returns false. If before expiration a signal was being processed, returns true.
*/ */
static boolean isReceiving(int waitMillis = 150); static boolean isReceiving(int waitMillis = 150);
/** /**
* Called every time the signal level changes (high to low or vice versa). Usually called by interrupt. * Called every time the signal level changes (high to low or vice versa). Usually called by interrupt.
*/ */
static void interruptHandler(); static void interruptHandler();
private: private:
static int8_t _interrupt; // Radio input interrupt static int8_t _interrupt; // Radio input interrupt
volatile static short _state; // State of decoding process. volatile static short _state; // State of decoding process.
static byte _minRepeats; static byte _minRepeats;
static NewRemoteReceiverCallBack _callback; static NewRemoteReceiverCallBack _callback;
static boolean _inCallback; // When true, the callback function is being executed; prevents re-entrance. static boolean _inCallback; // When true, the callback function is being executed; prevents re-entrance.
static boolean _enabled; // If true, monitoring and decoding is enabled. If false, interruptHandler will return immediately. static boolean _enabled; // If true, monitoring and decoding is enabled. If false, interruptHandler will return immediately.
}; };
#endif #endif
+134 -134
View File
@@ -1,134 +1,134 @@
/* /*
* NewRemoteSwitch library v1.1.0 (20130601) made by Randy Simons http://randysimons.nl/ * NewRemoteSwitch library v1.1.0 (20130601) made by Randy Simons http://randysimons.nl/
* See NewRemoteTransmitter.h for details. * See NewRemoteTransmitter.h for details.
* *
* License: GPLv3. See license.txt * License: GPLv3. See license.txt
*/ */
#include "NewRemoteTransmitter.h" #include "NewRemoteTransmitter.h"
NewRemoteTransmitter::NewRemoteTransmitter(unsigned long address, byte pin, unsigned int periodusec, byte repeats) { NewRemoteTransmitter::NewRemoteTransmitter(unsigned long address, byte pin, unsigned int periodusec, byte repeats) {
_address = address; _address = address;
_pin = pin; _pin = pin;
_periodusec = periodusec; _periodusec = periodusec;
_repeats = (1 << repeats) - 1; // I.e. _repeats = 2^repeats - 1 _repeats = (1 << repeats) - 1; // I.e. _repeats = 2^repeats - 1
pinMode(_pin, OUTPUT); pinMode(_pin, OUTPUT);
} }
void NewRemoteTransmitter::sendGroup(boolean switchOn) { void NewRemoteTransmitter::sendGroup(boolean switchOn) {
for (int8_t i = _repeats; i >= 0; i--) { for (int8_t i = _repeats; i >= 0; i--) {
_sendStartPulse(); _sendStartPulse();
_sendAddress(); _sendAddress();
// Do send group bit // Do send group bit
_sendBit(true); _sendBit(true);
// Switch on | off // Switch on | off
_sendBit(switchOn); _sendBit(switchOn);
// No unit. Is this actually ignored?.. // No unit. Is this actually ignored?..
_sendUnit(0); _sendUnit(0);
_sendStopPulse(); _sendStopPulse();
} }
} }
void NewRemoteTransmitter::sendUnit(byte unit, boolean switchOn) { void NewRemoteTransmitter::sendUnit(byte unit, boolean switchOn) {
for (int8_t i = _repeats; i >= 0; i--) { for (int8_t i = _repeats; i >= 0; i--) {
_sendStartPulse(); _sendStartPulse();
_sendAddress(); _sendAddress();
// No group bit // No group bit
_sendBit(false); _sendBit(false);
// Switch on | off // Switch on | off
_sendBit(switchOn); _sendBit(switchOn);
_sendUnit(unit); _sendUnit(unit);
_sendStopPulse(); _sendStopPulse();
} }
} }
void NewRemoteTransmitter::sendDim(byte unit, byte dimLevel) { void NewRemoteTransmitter::sendDim(byte unit, byte dimLevel) {
for (int8_t i = _repeats; i >= 0; i--) { for (int8_t i = _repeats; i >= 0; i--) {
_sendStartPulse(); _sendStartPulse();
_sendAddress(); _sendAddress();
// No group bit // No group bit
_sendBit(false); _sendBit(false);
// Switch type 'dim' // Switch type 'dim'
digitalWrite(_pin, HIGH); digitalWrite(_pin, HIGH);
delayMicroseconds(_periodusec); delayMicroseconds(_periodusec);
digitalWrite(_pin, LOW); digitalWrite(_pin, LOW);
delayMicroseconds(_periodusec); delayMicroseconds(_periodusec);
digitalWrite(_pin, HIGH); digitalWrite(_pin, HIGH);
delayMicroseconds(_periodusec); delayMicroseconds(_periodusec);
digitalWrite(_pin, LOW); digitalWrite(_pin, LOW);
delayMicroseconds(_periodusec); delayMicroseconds(_periodusec);
_sendUnit(unit); _sendUnit(unit);
for (int8_t j=3; j>=0; j--) { for (int8_t j=3; j>=0; j--) {
_sendBit(dimLevel & 1<<j); _sendBit(dimLevel & 1<<j);
} }
_sendStopPulse(); _sendStopPulse();
} }
} }
void NewRemoteTransmitter::_sendStartPulse(){ void NewRemoteTransmitter::_sendStartPulse(){
digitalWrite(_pin, HIGH); digitalWrite(_pin, HIGH);
delayMicroseconds(_periodusec); delayMicroseconds(_periodusec);
digitalWrite(_pin, LOW); digitalWrite(_pin, LOW);
delayMicroseconds(_periodusec * 10 + (_periodusec >> 1)); // Actually 10.5T insteat of 10.44T. Close enough. delayMicroseconds(_periodusec * 10 + (_periodusec >> 1)); // Actually 10.5T insteat of 10.44T. Close enough.
} }
void NewRemoteTransmitter::_sendAddress() { void NewRemoteTransmitter::_sendAddress() {
for (int8_t i=25; i>=0; i--) { for (int8_t i=25; i>=0; i--) {
_sendBit((_address >> i) & 1); _sendBit((_address >> i) & 1);
} }
} }
void NewRemoteTransmitter::_sendUnit(byte unit) { void NewRemoteTransmitter::_sendUnit(byte unit) {
for (int8_t i=3; i>=0; i--) { for (int8_t i=3; i>=0; i--) {
_sendBit(unit & 1<<i); _sendBit(unit & 1<<i);
} }
} }
void NewRemoteTransmitter::_sendStopPulse() { void NewRemoteTransmitter::_sendStopPulse() {
digitalWrite(_pin, HIGH); digitalWrite(_pin, HIGH);
delayMicroseconds(_periodusec); delayMicroseconds(_periodusec);
digitalWrite(_pin, LOW); digitalWrite(_pin, LOW);
delayMicroseconds(_periodusec * 40); delayMicroseconds(_periodusec * 40);
} }
void NewRemoteTransmitter::_sendBit(boolean isBitOne) { void NewRemoteTransmitter::_sendBit(boolean isBitOne) {
if (isBitOne) { if (isBitOne) {
// Send '1' // Send '1'
digitalWrite(_pin, HIGH); digitalWrite(_pin, HIGH);
delayMicroseconds(_periodusec); delayMicroseconds(_periodusec);
digitalWrite(_pin, LOW); digitalWrite(_pin, LOW);
delayMicroseconds(_periodusec * 5); delayMicroseconds(_periodusec * 5);
digitalWrite(_pin, HIGH); digitalWrite(_pin, HIGH);
delayMicroseconds(_periodusec); delayMicroseconds(_periodusec);
digitalWrite(_pin, LOW); digitalWrite(_pin, LOW);
delayMicroseconds(_periodusec); delayMicroseconds(_periodusec);
} else { } else {
// Send '0' // Send '0'
digitalWrite(_pin, HIGH); digitalWrite(_pin, HIGH);
delayMicroseconds(_periodusec); delayMicroseconds(_periodusec);
digitalWrite(_pin, LOW); digitalWrite(_pin, LOW);
delayMicroseconds(_periodusec); delayMicroseconds(_periodusec);
digitalWrite(_pin, HIGH); digitalWrite(_pin, HIGH);
delayMicroseconds(_periodusec); delayMicroseconds(_periodusec);
digitalWrite(_pin, LOW); digitalWrite(_pin, LOW);
delayMicroseconds(_periodusec * 5); delayMicroseconds(_periodusec * 5);
} }
} }
+103 -103
View File
@@ -1,103 +1,103 @@
/* /*
* NewRemoteSwitch library v1.1.0 (20130601) made by Randy Simons http://randysimons.nl/ * NewRemoteSwitch library v1.1.0 (20130601) made by Randy Simons http://randysimons.nl/
* *
* License: GPLv3. See license.txt * License: GPLv3. See license.txt
*/ */
#ifndef NewRemoteTransmitter_h #ifndef NewRemoteTransmitter_h
#define NewRemoteTransmitter_h #define NewRemoteTransmitter_h
#include <Arduino.h> #include <Arduino.h>
/** /**
* NewRemoteTransmitter provides a generic class for simulation of common RF remote controls, like the A-series * NewRemoteTransmitter provides a generic class for simulation of common RF remote controls, like the A-series
* 'Klik aan Klik uit'-system (http://www.klikaanklikuit.nl/), used to remotely switch lights etc. * 'Klik aan Klik uit'-system (http://www.klikaanklikuit.nl/), used to remotely switch lights etc.
* *
* This class is meant for new-style remotes, usually accompanied by receivers with "code learning" * This class is meant for new-style remotes, usually accompanied by receivers with "code learning"
* capabilities. For other remotes, use the RemoteTransmitter class. * capabilities. For other remotes, use the RemoteTransmitter class.
* *
* Hardware required for this library: a 433MHz/434MHz SAW oscillator transmitter, e.g. * Hardware required for this library: a 433MHz/434MHz SAW oscillator transmitter, e.g.
* http://www.sparkfun.com/products/10534 * http://www.sparkfun.com/products/10534
* http://www.conrad.nl/goto/?product=130428 * http://www.conrad.nl/goto/?product=130428
* *
* Notes: * Notes:
* - I measured the period length with an oscilloscope, using a A-series KAKU transmitter. Other devices * - I measured the period length with an oscilloscope, using a A-series KAKU transmitter. Other devices
* or manufacturers may use other period length. Use the ShowReceivedCodeNewRemote example to find the * or manufacturers may use other period length. Use the ShowReceivedCodeNewRemote example to find the
* period length for your devices. * period length for your devices.
* - You can copy the address of your "real" remotes, so you won't have to learn new codes into the receivers. * - You can copy the address of your "real" remotes, so you won't have to learn new codes into the receivers.
* In effect this duplicates a remote. But you can also pick a random number in the range 0..2^26-1. * In effect this duplicates a remote. But you can also pick a random number in the range 0..2^26-1.
*/ */
class NewRemoteTransmitter { class NewRemoteTransmitter {
public: public:
/** /**
* Constructor. * Constructor.
* *
* To obtain the correct period length, use the ShowReceivedCodeNewRemote example, or you * To obtain the correct period length, use the ShowReceivedCodeNewRemote example, or you
* can use an oscilloscope. * can use an oscilloscope.
* *
* @param address Address of this transmitter [0..2^26-1] Duplicate the address of your hardware, or choose a random number. * @param address Address of this transmitter [0..2^26-1] Duplicate the address of your hardware, or choose a random number.
* @param pin Output pin on Arduino to which the transmitter is connected * @param pin Output pin on Arduino to which the transmitter is connected
* @param periodusec Duration of one period, in microseconds. One bit takes 8 periods (but only 4 for 'dim' signal). * @param periodusec Duration of one period, in microseconds. One bit takes 8 periods (but only 4 for 'dim' signal).
* @param repeats [0..8] The 2log-Number of times the signal is repeated. The actual number of repeats will be 2^repeats. 2 would be bare minimum, 4 seems robust, 8 is maximum (and overkill). * @param repeats [0..8] The 2log-Number of times the signal is repeated. The actual number of repeats will be 2^repeats. 2 would be bare minimum, 4 seems robust, 8 is maximum (and overkill).
*/ */
NewRemoteTransmitter(unsigned long address, byte pin, unsigned int periodusec = 260, byte repeats = 4); NewRemoteTransmitter(unsigned long address, byte pin, unsigned int periodusec = 260, byte repeats = 4);
/** /**
* Send on/off command to the address group. * Send on/off command to the address group.
* *
* @param switchOn True to send "on" signal, false to send "off" signal. * @param switchOn True to send "on" signal, false to send "off" signal.
*/ */
void sendGroup(boolean switchOn); void sendGroup(boolean switchOn);
/** /**
* Send on/off command to an unit on the current address. * Send on/off command to an unit on the current address.
* *
* @param unit [0..15] target unit. * @param unit [0..15] target unit.
* @param switchOn True to send "on" signal, false to send "off" signal. * @param switchOn True to send "on" signal, false to send "off" signal.
*/ */
void sendUnit(byte unit, boolean switchOn); void sendUnit(byte unit, boolean switchOn);
/** /**
* Send dim value to an unit on the current address. * Send dim value to an unit on the current address.
* *
* @param unit [0..15] target unit. * @param unit [0..15] target unit.
* @param dimLevel [0..15] Dim level. 0 for off, 15 for brightest level. * @param dimLevel [0..15] Dim level. 0 for off, 15 for brightest level.
*/ */
void sendDim(byte unit, byte dimLevel); void sendDim(byte unit, byte dimLevel);
protected: protected:
unsigned long _address; // Address of this transmitter. unsigned long _address; // Address of this transmitter.
byte _pin; // Transmitter output pin byte _pin; // Transmitter output pin
unsigned int _periodusec; // Oscillator period in microseconds unsigned int _periodusec; // Oscillator period in microseconds
byte _repeats; // Number over repetitions of one telegram byte _repeats; // Number over repetitions of one telegram
/** /**
* Transmits start-pulse * Transmits start-pulse
*/ */
void _sendStartPulse(); void _sendStartPulse();
/** /**
* Transmits address part * Transmits address part
*/ */
void _sendAddress(); void _sendAddress();
/** /**
* Transmits unit part. * Transmits unit part.
* *
* @param unit [0-15] target unit. * @param unit [0-15] target unit.
*/ */
void _sendUnit(byte unit); void _sendUnit(byte unit);
/** /**
* Transmits stop pulse. * Transmits stop pulse.
*/ */
void _sendStopPulse(); void _sendStopPulse();
/** /**
* Transmits a single bit. * Transmits a single bit.
* *
* @param isBitOne True, to send '1', false to send '0'. * @param isBitOne True, to send '1', false to send '0'.
*/ */
void _sendBit(boolean isBitOne); void _sendBit(boolean isBitOne);
}; };
#endif #endif
+48 -48
View File
@@ -1,48 +1,48 @@
NewRemoteSwitch library v1.1.0 (BETA) for Arduino 1.0 NewRemoteSwitch library v1.1.0 (BETA) for Arduino 1.0
Made by Randy Simons http://randysimons.nl/ Made by Randy Simons http://randysimons.nl/
This library provides an easy class for Arduino, to send and receive signals This library provides an easy class for Arduino, to send and receive signals
used by some common "new style" 433MHz remote control switches. used by some common "new style" 433MHz remote control switches.
There are two styles of remote: There are two styles of remote:
- "old style", which uses switches or a dial to set the house code. Use the - "old style", which uses switches or a dial to set the house code. Use the
RemoteSwitch library instead. RemoteSwitch library instead.
- "new style", which use a button on the receivers to "learn" a signal. Use - "new style", which use a button on the receivers to "learn" a signal. Use
this library. this library.
License: GPLv3. See ./NewRemoteSwitch/license.txt License: GPLv3. See ./NewRemoteSwitch/license.txt
Latest source and wiki: https://bitbucket.org/fuzzillogic/433mhzforarduino Latest source and wiki: https://bitbucket.org/fuzzillogic/433mhzforarduino
Installation of library: Installation of library:
- Make sure Arduino is closed - Make sure Arduino is closed
- Copy the directory NewRemoteSwitch to the Arduino library directory (usually - Copy the directory NewRemoteSwitch to the Arduino library directory (usually
<Sketchbook directory>/libraries/) <Sketchbook directory>/libraries/)
See http://arduino.cc/en/Guide/Libraries for detailed instructions. See http://arduino.cc/en/Guide/Libraries for detailed instructions.
Default installation demo: Default installation demo:
- Connect the data-out-pin of a 433MHz receiver to digital pin 2. See photo. - Connect the data-out-pin of a 433MHz receiver to digital pin 2. See photo.
(Note: your hardware may have a different pin configuration!) (Note: your hardware may have a different pin configuration!)
- Start Arduino, and open the example: File -> Examples -> NewRemoteSwitch -> - Start Arduino, and open the example: File -> Examples -> NewRemoteSwitch ->
ShowReceivedCode or ShowReceivedCodeNewRemote. ShowReceivedCode or ShowReceivedCodeNewRemote.
- Compile, upload and run - Compile, upload and run
- Open serial monitor in Arduino (115200 baud) - Open serial monitor in Arduino (115200 baud)
- Press buttons on a 433MHz-remote, and watch the serial monitor - Press buttons on a 433MHz-remote, and watch the serial monitor
Changelog: Changelog:
NewRemoteSwitch library v1.1.0 (20130601) for Arduino 1.0 NewRemoteSwitch library v1.1.0 (20130601) for Arduino 1.0
- BUGFIX: in many occasions, when receiving a dim-level, the code was rejected - BUGFIX: in many occasions, when receiving a dim-level, the code was rejected
even if the signal was correct. even if the signal was correct.
- Support decoding A-series transmitters which transmit a dim-level in - Support decoding A-series transmitters which transmit a dim-level in
combination with an on-signal, instead of a dim-signal. combination with an on-signal, instead of a dim-signal.
- Uses NewRemodeCode::on, ::off, ::dim, ::on_with_dim instead of 0, 1, 2 and 3, - Uses NewRemodeCode::on, ::off, ::dim, ::on_with_dim instead of 0, 1, 2 and 3,
for better readability. This change is backwards compatible. for better readability. This change is backwards compatible.
- Updated examples to use the new NewRemodeCode::on, ::off, ::dim and - Updated examples to use the new NewRemodeCode::on, ::off, ::dim and
::on_with_dim notation. ::on_with_dim notation.
- Reduced memory usage (Flash, RAM) - Reduced memory usage (Flash, RAM)
NewRemoteSwitch library v1.0.0 (20121229) for Arduino 1.0 NewRemoteSwitch library v1.0.0 (20121229) for Arduino 1.0
- Support for receiving A-series Klik-aan-klik-uit remote. (NewRemoteReceiver) - Support for receiving A-series Klik-aan-klik-uit remote. (NewRemoteReceiver)
- With examples to test and demonstrate. - With examples to test and demonstrate.
@@ -1,23 +1,23 @@
= Protocol of klikaanklikuit A-series devices = = Protocol of klikaanklikuit A-series devices =
Copied from Wieltje, http://www.circuitsonline.net/forum/view/message/1181410#1181410, Copied from Wieltje, http://www.circuitsonline.net/forum/view/message/1181410#1181410,
but with slightly different timings, as measured on my device. but with slightly different timings, as measured on my device.
_ _ _ _
'0': | |_| |_____ (T,T,T,5T) '0': | |_| |_____ (T,T,T,5T)
_ _ _ _
'1': | |_____| |_ (T,5T,T,T) '1': | |_____| |_ (T,5T,T,T)
_ _ _ _
'dim': | |_| |_ (T,T,T,T) 'dim': | |_| |_ (T,T,T,T)
T = short period of ~260µs. Use the ShowReceivedCodeNewRemote example to find the T = short period of ~260µs. Use the ShowReceivedCodeNewRemote example to find the
actual period length for your devices. actual period length for your devices.
A full frame looks like this: A full frame looks like this:
- start pulse: 1T high, 10.44T low - start pulse: 1T high, 10.44T low
- 26 bit: Address - 26 bit: Address
- 1 bit: group bit - 1 bit: group bit
- 1 bit: on/off/[dim] - 1 bit: on/off/[dim]
- 4 bit: unit - 4 bit: unit
- [4 bit: dim level. Only present of [dim] is chosen] - [4 bit: dim level. Only present of [dim] is chosen]
- stop pulse: 1T high, 40T low - stop pulse: 1T high, 40T low
@@ -1,55 +1,55 @@
/** /**
* Demo for RF remote switch receiver. * Demo for RF remote switch receiver.
* For details, see NewRemoteReceiver.h! * For details, see NewRemoteReceiver.h!
* *
* Connect the transmitter to digital pin 11. * Connect the transmitter to digital pin 11.
* *
* This sketch demonstrates the use of the NewRemoteTransmitter class. * This sketch demonstrates the use of the NewRemoteTransmitter class.
* *
* When run, this sketch switches some pre-defined devices on and off in a loop. * When run, this sketch switches some pre-defined devices on and off in a loop.
* *
* NOTE: the actual receivers have the address and group numbers in this example * NOTE: the actual receivers have the address and group numbers in this example
* are only for demonstration! If you want to duplicate an existing remote, please * are only for demonstration! If you want to duplicate an existing remote, please
* try the "retransmitter"-example instead. * try the "retransmitter"-example instead.
* *
* To use this actual example, you'd need to "learn" the used code in the receivers * To use this actual example, you'd need to "learn" the used code in the receivers
* This sketch is unsuited for that. * This sketch is unsuited for that.
* *
*/ */
#include <NewRemoteTransmitter.h> #include <NewRemoteTransmitter.h>
// Create a transmitter on address 123, using digital pin 11 to transmit, // Create a transmitter on address 123, using digital pin 11 to transmit,
// with a period duration of 260ms (default), repeating the transmitted // with a period duration of 260ms (default), repeating the transmitted
// code 2^3=8 times. // code 2^3=8 times.
NewRemoteTransmitter transmitter(123, 11, 260, 3); NewRemoteTransmitter transmitter(123, 11, 260, 3);
void setup() { void setup() {
} }
void loop() { void loop() {
// Switch unit 2 off // Switch unit 2 off
transmitter.sendUnit(2, false); transmitter.sendUnit(2, false);
// Switch all devices in the group off // Switch all devices in the group off
transmitter.sendGroup(false); transmitter.sendGroup(false);
// Set unit 1 to dim-level 3 (range 0-15) // Set unit 1 to dim-level 3 (range 0-15)
transmitter.sendDim(1, 3); transmitter.sendDim(1, 3);
// Wait 5 seconds // Wait 5 seconds
delay(5000); delay(5000);
// Switch unit 2 on // Switch unit 2 on
transmitter.sendUnit(2, true); transmitter.sendUnit(2, true);
// Switch all devices in the group on // Switch all devices in the group on
transmitter.sendGroup(true); transmitter.sendGroup(true);
// Set unit 1 to dim-level 15, full brightness. // Set unit 1 to dim-level 15, full brightness.
transmitter.sendDim(1, 15); transmitter.sendDim(1, 15);
// Wait 5 seconds // Wait 5 seconds
delay(5000); delay(5000);
} }
+10 -10
View File
@@ -1,11 +1,11 @@
NewRemoteReceiver KEYWORD1 NewRemoteReceiver KEYWORD1
NewRemoteCode KEYWORD1 NewRemoteCode KEYWORD1
isReceiving KEYWORD2 isReceiving KEYWORD2
init KEYWORD2 init KEYWORD2
enable KEYWORD2 enable KEYWORD2
disable KEYWORD2 disable KEYWORD2
deinit KEYWORD2 deinit KEYWORD2
NewRemoteTransmitter KEYWORD1 NewRemoteTransmitter KEYWORD1
sendGroup KEYWORD2 sendGroup KEYWORD2
sendUnit KEYWORD2 sendUnit KEYWORD2
sendDim KEYWORD2 sendDim KEYWORD2
@@ -87,4 +87,4 @@ void loop() {
+61 -61
View File
@@ -1,62 +1,62 @@
RemoteSensor library v1.0.1 (20120213) for Arduino 1.0 RemoteSensor library v1.0.1 (20120213) for Arduino 1.0
Made by Randy Simons http://randysimons.nl/ Made by Randy Simons http://randysimons.nl/
This library provides an easy class for Arduino, to send and receive signals This library provides an easy class for Arduino, to send and receive signals
used by some common weather stations using remote 433MHz sensors, like those used by some common weather stations using remote 433MHz sensors, like those
made by Cresta. made by Cresta.
E.g. http://www.cresta.nl/index.php?Itemid=2&option=com_zoo&view=item&category_id=32&item_id=281&lang=en E.g. http://www.cresta.nl/index.php?Itemid=2&option=com_zoo&view=item&category_id=32&item_id=281&lang=en
Cresta is just a brandname. The original OEM seems to be Hideki Electronics. Cresta is just a brandname. The original OEM seems to be Hideki Electronics.
There are other brands which use the same hardware and / or protocol. As far There are other brands which use the same hardware and / or protocol. As far
as I know these include Mebus, Irox, Honeywell, Cresta and RST. as I know these include Mebus, Irox, Honeywell, Cresta and RST.
This software is based on the work of Oopsje. See docs/CrestaProtocol.pdf This software is based on the work of Oopsje. See docs/CrestaProtocol.pdf
See SensorTransmitter.h and SensorReciver.h for details! See SensorTransmitter.h and SensorReciver.h for details!
License: GPLv3. See ./RemoteSensor/license.txt License: GPLv3. See ./RemoteSensor/license.txt
Latest source and wiki: https://bitbucket.org/fuzzillogic/433mhzforarduino Latest source and wiki: https://bitbucket.org/fuzzillogic/433mhzforarduino
Installation of library: Installation of library:
- Make sure Arduino is closed - Make sure Arduino is closed
- Copy the directory RemoteSensor to the Arduino library directory (usually - Copy the directory RemoteSensor to the Arduino library directory (usually
<Sketchbook directory>/libraries/) <Sketchbook directory>/libraries/)
See http://arduino.cc/en/Guide/Libraries for detailed instructions. See http://arduino.cc/en/Guide/Libraries for detailed instructions.
Default installation sender & demo: Default installation sender & demo:
- Connect tha data-in-pin of a 433MHz transmitter to digital pin 11. See - Connect tha data-in-pin of a 433MHz transmitter to digital pin 11. See
docs/hardware setup.jpg. docs/hardware setup.jpg.
(Note: your hardware may have a different pin configuration!) (Note: your hardware may have a different pin configuration!)
- Start Arduino, and open the example: File -> Examples -> RemoteSensor -> - Start Arduino, and open the example: File -> Examples -> RemoteSensor ->
ThermoHygroTransmitter ThermoHygroTransmitter
- Alter addresses/devices to reflect your own setup. Otherwise nothing will - Alter addresses/devices to reflect your own setup. Otherwise nothing will
happen. happen.
- Compile, upload and run! - Compile, upload and run!
Default installation receiver & demo: Default installation receiver & demo:
- Connect the data-out-pin of a 433MHz receiver to digital pin 2. See photo. - Connect the data-out-pin of a 433MHz receiver to digital pin 2. See photo.
(Note: your hardware may have a different pin configuration!) (Note: your hardware may have a different pin configuration!)
- Start Arduino, and open the example: File -> Examples -> RemoteSensor -> - Start Arduino, and open the example: File -> Examples -> RemoteSensor ->
ThermoHygroReceiver ThermoHygroReceiver
- Compile, upload and run - Compile, upload and run
- Open serial monitor in Arduino (115200 baud) - Open serial monitor in Arduino (115200 baud)
- Wait for your 433MHz-sensor to transmit (less than 1 minute), and watch the - Wait for your 433MHz-sensor to transmit (less than 1 minute), and watch the
serial monitor serial monitor
Changelog: Changelog:
RemoteSensor library v1.0.2 (20130601) for Arduino 1.0 RemoteSensor library v1.0.2 (20130601) for Arduino 1.0
- Reduced memory usage (Flash, RAM). Because of this, a small backwards - Reduced memory usage (Flash, RAM). Because of this, a small backwards
incompatibility is introduced: The last parameter of incompatibility is introduced: The last parameter of
SensorReceiver::decodeThermoHygro now is a byte instead of short. SensorReceiver::decodeThermoHygro now is a byte instead of short.
- Dropped support for Arduino pre-1.0 - Dropped support for Arduino pre-1.0
RemoteSensor library v1.0.1 (20120213) for Arduino 0022/1.0 RemoteSensor library v1.0.1 (20120213) for Arduino 0022/1.0
- Ignore obviously too short or too long signals in SensorReceiver, for better - Ignore obviously too short or too long signals in SensorReceiver, for better
recognition rate. recognition rate.
- Support for Arduino 1.0. - Support for Arduino 1.0.
RemoteSensor library v1.0.0 (20110919) for Arduino 0022 RemoteSensor library v1.0.0 (20110919) for Arduino 0022
- Initial version - Initial version
+110 -110
View File
@@ -1,111 +1,111 @@
/* /*
* RemoteSensor library v1.0.2 (20130601) for Arduino 1.0 * RemoteSensor library v1.0.2 (20130601) for Arduino 1.0
* *
* This library encodes, encrypts en transmits data to * This library encodes, encrypts en transmits data to
* remote weather stations made by Hideki Electronics.. * remote weather stations made by Hideki Electronics..
* *
* Copyright 2011-2013 by Randy Simons http://randysimons.nl/ * Copyright 2011-2013 by Randy Simons http://randysimons.nl/
* *
* Parts of this code based on Oopsje's CrestaProtocol.pdf, for which * Parts of this code based on Oopsje's CrestaProtocol.pdf, for which
* I thank him very much! * I thank him very much!
* *
* License: GPLv3. See license.txt * License: GPLv3. See license.txt
*/ */
#ifndef SensorTransmitter_h #ifndef SensorTransmitter_h
#define SensorTransmitter_h #define SensorTransmitter_h
#include <Arduino.h> #include <Arduino.h>
/** /**
* SensorTransmitter provides a generic class to simulate Cresta weather sensors, for use * SensorTransmitter provides a generic class to simulate Cresta weather sensors, for use
* with Cresta weather stations. * with Cresta weather stations.
* E.g. http://www.cresta.nl/index.php?Itemid=2&option=com_zoo&view=item&category_id=32&item_id=281&lang=en * E.g. http://www.cresta.nl/index.php?Itemid=2&option=com_zoo&view=item&category_id=32&item_id=281&lang=en
* *
* Cresta is just a brand name. The original OEM seems to be Hideki Electronics. There are * Cresta is just a brand name. The original OEM seems to be Hideki Electronics. There are
* other brands which use the same hardware and / or protocol. As far as I know these include * other brands which use the same hardware and / or protocol. As far as I know these include
* Mebus, Irox, Honeywell, Cresta and RST. * Mebus, Irox, Honeywell, Cresta and RST.
* *
* Hardware required for this library: a 433MHz/434MHz SAW oscillator transmitter, e.g. * Hardware required for this library: a 433MHz/434MHz SAW oscillator transmitter, e.g.
* http://www.sparkfun.com/products/10534 * http://www.sparkfun.com/products/10534
* http://www.conrad.nl/goto/?product=130428 * http://www.conrad.nl/goto/?product=130428
*/ */
class SensorTransmitter { class SensorTransmitter {
public: public:
/** /**
* Initializes the transmitter. About the random id: "A sensor selects a random value * Initializes the transmitter. About the random id: "A sensor selects a random value
* in the range of column 1 when it is reset. It keeps the same ID until it is reset again." * in the range of column 1 when it is reset. It keeps the same ID until it is reset again."
* You can leave it at 0 for most purposes * You can leave it at 0 for most purposes
* The transmitter pin is set in OUTPUT mode; you don't have to do this yourself. * The transmitter pin is set in OUTPUT mode; you don't have to do this yourself.
* *
* @param transmitterPin Arduino-pin connected to the 433MHz transmitter * @param transmitterPin Arduino-pin connected to the 433MHz transmitter
* @param randomId A "random" value in the range [0..31] * @param randomId A "random" value in the range [0..31]
*/ */
SensorTransmitter(byte transmitterPin, byte randomId); SensorTransmitter(byte transmitterPin, byte randomId);
/** /**
* Sends a raw sensor package. Before transmitting, the data is encrypted and checksums are * Sends a raw sensor package. Before transmitting, the data is encrypted and checksums are
* added. The buffer of the data doesn't need to have room for the checksums, as the data is * added. The buffer of the data doesn't need to have room for the checksums, as the data is
* copied internally to a new buffer which is always large enough. * copied internally to a new buffer which is always large enough.
* However, the data must be valid! * However, the data must be valid!
* *
* The data is transmitted 3 times. * The data is transmitted 3 times.
* *
* Note that this is a static method. * Note that this is a static method.
* *
* @param transmitterPin Arduino-pin connected to the 433MHz transmitter * @param transmitterPin Arduino-pin connected to the 433MHz transmitter
* @param data Pointer to data to transmit * @param data Pointer to data to transmit
*/ */
static void sendPackage(byte transmitterPin, byte *data); static void sendPackage(byte transmitterPin, byte *data);
protected: protected:
byte _transmitterPin; byte _transmitterPin;
byte _randomId; byte _randomId;
private: private:
/** /**
* Sends data as manchester encoded stream * Sends data as manchester encoded stream
*/ */
static void sendManchesterPackage(byte transmitterPin, byte *data, byte cnt); static void sendManchesterPackage(byte transmitterPin, byte *data, byte cnt);
/** /**
* Sends a single byte as manchester encoded stream * Sends a single byte as manchester encoded stream
*/ */
static void sendManchesterByte(byte transmitterPin, byte b); static void sendManchesterByte(byte transmitterPin, byte b);
/** /**
* Encryption and checksum * Encryption and checksum
*/ */
static byte encryptAndAddCheck(byte *buffer); static byte encryptAndAddCheck(byte *buffer);
static byte secondCheck(byte b); static byte secondCheck(byte b);
static byte encryptByte(byte b); static byte encryptByte(byte b);
}; };
class ThermoHygroTransmitter : public SensorTransmitter { class ThermoHygroTransmitter : public SensorTransmitter {
public: public:
/** /**
* Mimics a Thermo / Hygro sensor. The channel of this device can be 1..5, but note * Mimics a Thermo / Hygro sensor. The channel of this device can be 1..5, but note
* that only the more expensive receivers can use channels 4 and 5. However, for use * that only the more expensive receivers can use channels 4 and 5. However, for use
* in conjunction with SensorReceiver this is of no concern. * in conjunction with SensorReceiver this is of no concern.
* *
* @param transmitterPin Arduino-pin connected to the 433MHz transmitter * @param transmitterPin Arduino-pin connected to the 433MHz transmitter
* @param randomId A "random" value in the range [0..31] * @param randomId A "random" value in the range [0..31]
* @channel The channel of this sensor, range [1..5] * @channel The channel of this sensor, range [1..5]
* @see SensorTransmitter::SensorTransmitter (constructor) * @see SensorTransmitter::SensorTransmitter (constructor)
*/ */
ThermoHygroTransmitter(byte transmitterPin, byte randomId, byte channel); ThermoHygroTransmitter(byte transmitterPin, byte randomId, byte channel);
/** /**
* Sends temperature and humidity. * Sends temperature and humidity.
* *
* @param temperature 10x the actual temperature. You want to send 23,5 degrees, then temperature should be 235. * @param temperature 10x the actual temperature. You want to send 23,5 degrees, then temperature should be 235.
* @param humidty Humidity in percentage-points REL. Thus, for 34% REH humidity should be 34. * @param humidty Humidity in percentage-points REL. Thus, for 34% REH humidity should be 34.
*/ */
void sendTempHumi(int temperature, byte humidity); void sendTempHumi(int temperature, byte humidity);
private: private:
byte _channel; // Note: internally, the channels for the thermo/hygro-sensor are mapped as follow: byte _channel; // Note: internally, the channels for the thermo/hygro-sensor are mapped as follow:
// 1=>1, 2=>2, 3=>3, 4=>5, 5=>6. // 1=>1, 2=>2, 3=>3, 4=>5, 5=>6.
// This because interally the rain sensor, UV sensor and anemometer are on channel 4. // This because interally the rain sensor, UV sensor and anemometer are on channel 4.
}; };
#endif #endif
@@ -51,4 +51,4 @@ void retransmit(byte *data) {
noInterrupts(); noInterrupts();
SensorReceiver::enable(); SensorReceiver::enable();
} }
@@ -25,4 +25,4 @@
// Wait two seconds before sending next. // Wait two seconds before sending next.
delay(2000); delay(2000);
} }
} }
+8 -8
View File
@@ -1,9 +1,9 @@
SensorReceiver KEYWORD1 SensorReceiver KEYWORD1
init KEYWORD2 init KEYWORD2
decodeThermoHygro KEYWORD2 decodeThermoHygro KEYWORD2
enable KEYWORD2 enable KEYWORD2
disable KEYWORD2 disable KEYWORD2
interruptHandler KEYWORD2 interruptHandler KEYWORD2
SensorTransmitter KEYWORD1 SensorTransmitter KEYWORD1
sendPackage KEYWORD2 sendPackage KEYWORD2
ThermoHygroTransmitter KEYWORD1 ThermoHygroTransmitter KEYWORD1
+80 -80
View File
@@ -1,81 +1,81 @@
RemoteSwitch library v2.3.0 (20121229) for Arduino 1.0 RemoteSwitch library v2.3.0 (20121229) for Arduino 1.0
Made by Randy Simons http://randysimons.nl/ Made by Randy Simons http://randysimons.nl/
This library provides an easy class for Arduino, to send and receive signals This library provides an easy class for Arduino, to send and receive signals
used by some common "old style" 433MHz remote control switches. used by some common "old style" 433MHz remote control switches.
There are two styles of remote: There are two styles of remote:
- "old style", which uses switches or a dial to set the house code. Use this - "old style", which uses switches or a dial to set the house code. Use this
library. library.
- "new style", which use a button on the receivers to "learn" a signal. Use - "new style", which use a button on the receivers to "learn" a signal. Use
the NewRemoteSwitch library instead. the NewRemoteSwitch library instead.
See RemoteTransmitter.h and RemoteReceiver.h for details! See RemoteTransmitter.h and RemoteReceiver.h for details!
License: GPLv3. See ./RemoteSwitch/license.txt License: GPLv3. See ./RemoteSwitch/license.txt
Latest source and wiki: https://bitbucket.org/fuzzillogic/433mhzforarduino Latest source and wiki: https://bitbucket.org/fuzzillogic/433mhzforarduino
Installation of library: Installation of library:
- Make sure Arduino is closed - Make sure Arduino is closed
- Copy the directory RemoteSwitch to the Arduino library directory (usually - Copy the directory RemoteSwitch to the Arduino library directory (usually
<Sketchbook directory>/libraries/) <Sketchbook directory>/libraries/)
See http://arduino.cc/en/Guide/Libraries for detailed instructions. See http://arduino.cc/en/Guide/Libraries for detailed instructions.
Default installation sender & demo: Default installation sender & demo:
- Connect tha data-in-pin of a 433MHz transmitter to digital pin 11. See - Connect tha data-in-pin of a 433MHz transmitter to digital pin 11. See
docs/hardware setup.jpg. docs/hardware setup.jpg.
(Note: your hardware may have a different pin configuration!) (Note: your hardware may have a different pin configuration!)
- Start Arduino, and open the example: File -> Examples -> RemoteSwitch -> - Start Arduino, and open the example: File -> Examples -> RemoteSwitch ->
LightShow LightShow
- Alter addresses/devices to reflect your own setup. Otherwise nothing will - Alter addresses/devices to reflect your own setup. Otherwise nothing will
happen. happen.
- Compile, upload and run! - Compile, upload and run!
Default installation receiver & demo: Default installation receiver & demo:
- Connect the data-out-pin of a 433MHz receiver to digital pin 2. See photo. - Connect the data-out-pin of a 433MHz receiver to digital pin 2. See photo.
(Note: your hardware may have a different pin configuration!) (Note: your hardware may have a different pin configuration!)
- Start Arduino, and open the example: File -> Examples -> RemoteSwitch -> - Start Arduino, and open the example: File -> Examples -> RemoteSwitch ->
ShowReceivedCode or ShowReceivedCodeNewKaku, depending on your remote. ShowReceivedCode or ShowReceivedCodeNewKaku, depending on your remote.
- Compile, upload and run - Compile, upload and run
- Open serial monitor in Arduino (115200 baud) - Open serial monitor in Arduino (115200 baud)
- Press buttons on a 433MHz-remote, and watch the serial monitor - Press buttons on a 433MHz-remote, and watch the serial monitor
Notes: Notes:
- These transmitters often use the PT2262 IC, or equivalent. For details about - These transmitters often use the PT2262 IC, or equivalent. For details about
the waveforms used by these remotes, the datasheet of the PT2262 is provided. the waveforms used by these remotes, the datasheet of the PT2262 is provided.
Page 4 and 5 will be of most interest. Page 4 and 5 will be of most interest.
Changelog: Changelog:
RemoteSwitch library v2.3.0 (20121229) for Arduino 1.0 RemoteSwitch library v2.3.0 (20121229) for Arduino 1.0
- Improved reception quality by filtering too short pulses. - Improved reception quality by filtering too short pulses.
- Dropped pre-v1.0 Arduino support. - Dropped pre-v1.0 Arduino support.
- Added RemoteReceiver::deinit() - Added RemoteReceiver::deinit()
RemoteSwitch library v2.2.1 (20120314) for Arduino 0022/1.0 RemoteSwitch library v2.2.1 (20120314) for Arduino 0022/1.0
- Fixed Elro code, it caused memory corruption. - Fixed Elro code, it caused memory corruption.
- Renamed old-style .pde files to new-style .ino - Renamed old-style .pde files to new-style .ino
RemoteSwitch library v2.2.0 (20120213) for Arduino 0022/1.0 RemoteSwitch library v2.2.0 (20120213) for Arduino 0022/1.0
- Added support for Elro switches (http://www.elro.eu/en/m/products/category/home_automation/home_control) - Added support for Elro switches (http://www.elro.eu/en/m/products/category/home_automation/home_control)
(untested; I don't have these kind of devices) (untested; I don't have these kind of devices)
- Allowed the number of repeated signals transmitted by RemoteTransmitter to be - Allowed the number of repeated signals transmitted by RemoteTransmitter to be
changed. changed.
- By default, 16 instead of 8 repeats are sent. - By default, 16 instead of 8 repeats are sent.
- Support for Arduino 1.0. - Support for Arduino 1.0.
- Added Datasheet PT2262, which (or equivalent) is often used in the transmitters. - Added Datasheet PT2262, which (or equivalent) is often used in the transmitters.
- RemoteReceiver::isReceiving timeout changed to 150ms; 100ms was too short. - RemoteReceiver::isReceiving timeout changed to 150ms; 100ms was too short.
RemoteSwitch library v2.1.1 (20110920) for Arduino 0022 RemoteSwitch library v2.1.1 (20110920) for Arduino 0022
- Improved RemoteReceiver::isReceiving - Improved RemoteReceiver::isReceiving
RemoteSwitch library v2.1.0 (20110919) for Arduino 0022 RemoteSwitch library v2.1.0 (20110919) for Arduino 0022
- Changed classnames from *Switch to *Transmitter - Changed classnames from *Switch to *Transmitter
- Added RemoteTransmitter::sendCode. See example "retransmitter". - Added RemoteTransmitter::sendCode. See example "retransmitter".
- RemoteReceiver::interruptHandler() is now public, for use with InterruptChain - RemoteReceiver::interruptHandler() is now public, for use with InterruptChain
RemoteSwitch library v2.0.0 (20100130) for Arduino 0017 RemoteSwitch library v2.0.0 (20100130) for Arduino 0017
- Complete rewrite; can now receive and decode signals directly from - Complete rewrite; can now receive and decode signals directly from
the receiver's digital out. the receiver's digital out.
+193 -193
View File
@@ -1,193 +1,193 @@
/* /*
* RemoteSwitch library v2.3.0 (20121229) made by Randy Simons http://randysimons.nl/ * RemoteSwitch library v2.3.0 (20121229) made by Randy Simons http://randysimons.nl/
* See RemoteReceiver.h for details. * See RemoteReceiver.h for details.
* *
* License: GPLv3. See license.txt * License: GPLv3. See license.txt
*/ */
#include "RemoteReceiver.h" #include "RemoteReceiver.h"
/************ /************
* RemoteReceiver * RemoteReceiver
************/ ************/
int8_t RemoteReceiver::_interrupt; int8_t RemoteReceiver::_interrupt;
volatile int8_t RemoteReceiver::_state; volatile int8_t RemoteReceiver::_state;
byte RemoteReceiver::_minRepeats; byte RemoteReceiver::_minRepeats;
RemoteReceiverCallBack RemoteReceiver::_callback; RemoteReceiverCallBack RemoteReceiver::_callback;
boolean RemoteReceiver::_inCallback = false; boolean RemoteReceiver::_inCallback = false;
boolean RemoteReceiver::_enabled = false; boolean RemoteReceiver::_enabled = false;
void RemoteReceiver::init(int8_t interrupt, byte minRepeats, RemoteReceiverCallBack callback) { void RemoteReceiver::init(int8_t interrupt, byte minRepeats, RemoteReceiverCallBack callback) {
_interrupt = interrupt; _interrupt = interrupt;
_minRepeats = minRepeats; _minRepeats = minRepeats;
_callback = callback; _callback = callback;
enable(); enable();
if (_interrupt >= 0) { if (_interrupt >= 0) {
attachInterrupt(_interrupt, interruptHandler, CHANGE); attachInterrupt(_interrupt, interruptHandler, CHANGE);
} }
} }
void RemoteReceiver::enable() { void RemoteReceiver::enable() {
_state = -1; _state = -1;
_enabled = true; _enabled = true;
} }
void RemoteReceiver::disable() { void RemoteReceiver::disable() {
_enabled = false; _enabled = false;
} }
void RemoteReceiver::deinit() { void RemoteReceiver::deinit() {
_enabled = false; _enabled = false;
if (_interrupt >= 0) { if (_interrupt >= 0) {
detachInterrupt(_interrupt); detachInterrupt(_interrupt);
} }
} }
void RemoteReceiver::interruptHandler() { void RemoteReceiver::interruptHandler() {
if (!_enabled) { if (!_enabled) {
return; return;
} }
static unsigned int period; // Calculated duration of 1 period static unsigned int period; // Calculated duration of 1 period
static byte receivedBit; // Contains "bit" currently receiving static byte receivedBit; // Contains "bit" currently receiving
static unsigned long receivedCode; // Contains received code static unsigned long receivedCode; // Contains received code
static unsigned long previousCode; // Contains previous received code static unsigned long previousCode; // Contains previous received code
static byte repeats = 0; // The number of times the an identical code is received in a row. static byte repeats = 0; // The number of times the an identical code is received in a row.
static unsigned long edgeTimeStamp[3] = {0, }; // Timestamp of edges static unsigned long edgeTimeStamp[3] = {0, }; // Timestamp of edges
static unsigned int min1Period, max1Period, min3Period, max3Period; static unsigned int min1Period, max1Period, min3Period, max3Period;
static bool skip; static bool skip;
// Filter out too short pulses. This method works as a low pass filter. // Filter out too short pulses. This method works as a low pass filter.
edgeTimeStamp[1] = edgeTimeStamp[2]; edgeTimeStamp[1] = edgeTimeStamp[2];
edgeTimeStamp[2] = micros(); edgeTimeStamp[2] = micros();
if (skip) { if (skip) {
skip = false; skip = false;
return; return;
} }
if (_state >= 0 && edgeTimeStamp[2]-edgeTimeStamp[1] < min1Period) { if (_state >= 0 && edgeTimeStamp[2]-edgeTimeStamp[1] < min1Period) {
// Last edge was too short. // Last edge was too short.
// Skip this edge, and the next too. // Skip this edge, and the next too.
skip = true; skip = true;
return; return;
} }
unsigned int duration = edgeTimeStamp[1] - edgeTimeStamp[0]; unsigned int duration = edgeTimeStamp[1] - edgeTimeStamp[0];
edgeTimeStamp[0] = edgeTimeStamp[1]; edgeTimeStamp[0] = edgeTimeStamp[1];
// Note that if state>=0, duration is always >= 1 period. // Note that if state>=0, duration is always >= 1 period.
if (_state==-1) { // Waiting for sync-signal if (_state==-1) { // Waiting for sync-signal
if (duration>3720) { // =31*120 minimal time between two edges before decoding starts. if (duration>3720) { // =31*120 minimal time between two edges before decoding starts.
// Sync signal received.. Preparing for decoding // Sync signal received.. Preparing for decoding
period=duration/31; period=duration/31;
receivedCode=previousCode=repeats=0; receivedCode=previousCode=repeats=0;
// Allow for large error-margin. ElCheapo-hardware :( // Allow for large error-margin. ElCheapo-hardware :(
min1Period=period*4/10; // Avoid floating point math; saves memory. min1Period=period*4/10; // Avoid floating point math; saves memory.
max1Period=period*16/10; max1Period=period*16/10;
min3Period=period*23/10; min3Period=period*23/10;
max3Period=period*37/10; max3Period=period*37/10;
} }
else { else {
return; return;
} }
} else if (_state<48) { // Decoding message } else if (_state<48) { // Decoding message
receivedBit <<= 1; receivedBit <<= 1;
// bit part durations can ONLY be 1 or 3 periods. // bit part durations can ONLY be 1 or 3 periods.
if (duration<=max1Period) { if (duration<=max1Period) {
receivedBit &= B1110; // Clear LSB of receivedBit receivedBit &= B1110; // Clear LSB of receivedBit
} }
else if (duration>=min3Period && duration<=max3Period) { else if (duration>=min3Period && duration<=max3Period) {
receivedBit |= B1; // Set LSB of receivedBit receivedBit |= B1; // Set LSB of receivedBit
} }
else { // Otherwise the entire sequence is invalid else { // Otherwise the entire sequence is invalid
_state=-1; _state=-1;
return; return;
} }
if ((_state%4)==3) { // Last bit part? if ((_state%4)==3) { // Last bit part?
// Shift // Shift
receivedCode*=3; receivedCode*=3;
// Only 4 LSB's are used; trim the rest. // Only 4 LSB's are used; trim the rest.
switch (receivedBit & B1111) { switch (receivedBit & B1111) {
case B0101: // short long short long == B0101 case B0101: // short long short long == B0101
// bit "0" received // bit "0" received
receivedCode+=0; // I hope the optimizer handles this ;) receivedCode+=0; // I hope the optimizer handles this ;)
break; break;
case B1010: // long short long short == B1010 case B1010: // long short long short == B1010
// bit "1" received // bit "1" received
receivedCode+=1; receivedCode+=1;
break; break;
case B0110: // short long long short case B0110: // short long long short
// bit "f" received // bit "f" received
receivedCode+=2; receivedCode+=2;
break; break;
default: default:
// Bit was rubbish. Abort. // Bit was rubbish. Abort.
_state=-1; _state=-1;
return; return;
} }
} }
} else if (_state==48) { // Waiting for sync bit part 1 } else if (_state==48) { // Waiting for sync bit part 1
// Must be 1 period. // Must be 1 period.
if (duration>max1Period) { if (duration>max1Period) {
_state=-1; _state=-1;
return; return;
} }
} else { // Waiting for sync bit part 2 } else { // Waiting for sync bit part 2
// Must be 31 periods. // Must be 31 periods.
if (duration<period*25 || duration>period*36) { if (duration<period*25 || duration>period*36) {
_state=-1; _state=-1;
return; return;
} }
// receivedCode is a valid code! // receivedCode is a valid code!
if (receivedCode!=previousCode) { if (receivedCode!=previousCode) {
repeats=0; repeats=0;
previousCode=receivedCode; previousCode=receivedCode;
} }
repeats++; repeats++;
if (repeats>=_minRepeats) { if (repeats>=_minRepeats) {
if (!_inCallback) { if (!_inCallback) {
_inCallback = true; _inCallback = true;
(_callback)(receivedCode, period); (_callback)(receivedCode, period);
_inCallback = false; _inCallback = false;
} }
// Reset after callback. // Reset after callback.
_state=-1; _state=-1;
return; return;
} }
// Reset for next round // Reset for next round
receivedCode = 0; receivedCode = 0;
_state=0; // no need to wait for another sync-bit! _state=0; // no need to wait for another sync-bit!
return; return;
} }
_state++; _state++;
return; return;
} }
boolean RemoteReceiver::isReceiving(int waitMillis) { boolean RemoteReceiver::isReceiving(int waitMillis) {
unsigned long startTime=millis(); unsigned long startTime=millis();
int waited; // Signed int! int waited; // Signed int!
do { do {
if (_state == 48) { // Abort if a valid code has been received in the mean time if (_state == 48) { // Abort if a valid code has been received in the mean time
return true; return true;
} }
waited = (millis()-startTime); waited = (millis()-startTime);
} while(waited>=0 && waited <= waitMillis); // Yes, clock wraps every 50 days. And then you'd have to wait for a looooong time. } while(waited>=0 && waited <= waitMillis); // Yes, clock wraps every 50 days. And then you'd have to wait for a looooong time.
return false; return false;
} }
+88 -88
View File
@@ -1,88 +1,88 @@
/* /*
* RemoteSwitch library v2.3.0 (20121229) made by Randy Simons http://randysimons.nl/ * RemoteSwitch library v2.3.0 (20121229) made by Randy Simons http://randysimons.nl/
* *
* License: GPLv3. See license.txt * License: GPLv3. See license.txt
*/ */
#ifndef RemoteReceiver_h #ifndef RemoteReceiver_h
#define RemoteReceiver_h #define RemoteReceiver_h
#include <Arduino.h> #include <Arduino.h>
typedef void (*RemoteReceiverCallBack)(unsigned long, unsigned int); typedef void (*RemoteReceiverCallBack)(unsigned long, unsigned int);
/** /**
* See RemoteSwitch for introduction. * See RemoteSwitch for introduction.
* *
* RemoteReceiver decodes the signal received from a 433MHz-receiver, like the "KlikAanKlikUit"-system * RemoteReceiver decodes the signal received from a 433MHz-receiver, like the "KlikAanKlikUit"-system
* as well as the signal sent by the RemoteSwtich class. When a correct signal is received, * as well as the signal sent by the RemoteSwtich class. When a correct signal is received,
* a user-defined callback function is called. * a user-defined callback function is called.
* *
* Note that in the callback function, the interrupts are still disabled. You can enabled them, if needed. * Note that in the callback function, the interrupts are still disabled. You can enabled them, if needed.
* A call to the callback must b finished before RemoteReceiver will call the callback function again, thus * A call to the callback must b finished before RemoteReceiver will call the callback function again, thus
* there is no re-entrant problem. * there is no re-entrant problem.
* *
* When sending your own code using RemoteSwich, disable() the receiver first. * When sending your own code using RemoteSwich, disable() the receiver first.
* *
* This is a pure static class, for simplicity and to limit memory-use. * This is a pure static class, for simplicity and to limit memory-use.
*/ */
class RemoteReceiver { class RemoteReceiver {
public: public:
/** /**
* Initializes the decoder. * Initializes the decoder.
* *
* If interrupt >= 0, init will register pin <interrupt> to this library. * If interrupt >= 0, init will register pin <interrupt> to this library.
* If interrupt < 0, no interrupt is registered. In that case, you have to call interruptHandler() * If interrupt < 0, no interrupt is registered. In that case, you have to call interruptHandler()
* yourself whenever the output of the receiver changes, or you can use InterruptChain. * yourself whenever the output of the receiver changes, or you can use InterruptChain.
* *
* @param interrupt The interrupt as is used by Arduino's attachInterrupt function. See attachInterrupt for details. * @param interrupt The interrupt as is used by Arduino's attachInterrupt function. See attachInterrupt for details.
If < 0, you must call interruptHandler() yourself. If < 0, you must call interruptHandler() yourself.
* @param minRepeats The number of times the same code must be received in a row before the callback is calles * @param minRepeats The number of times the same code must be received in a row before the callback is calles
* @param callback Pointer to a callback function, with signature void (*func)(unsigned long, unsigned int). First parameter is the decoded data, the second the period of the timing. * @param callback Pointer to a callback function, with signature void (*func)(unsigned long, unsigned int). First parameter is the decoded data, the second the period of the timing.
*/ */
static void init(int8_t interrupt, byte minRepeats, RemoteReceiverCallBack callback); static void init(int8_t interrupt, byte minRepeats, RemoteReceiverCallBack callback);
/** /**
* Enable decoding. No need to call enable() after init(). * Enable decoding. No need to call enable() after init().
*/ */
static void enable(); static void enable();
/** /**
* Disable decoding. You can re-enable decoding by calling enable(); * Disable decoding. You can re-enable decoding by calling enable();
*/ */
static void disable(); static void disable();
/** /**
* Deinitializes the decoder. Disables decoding and detaches the interrupt handler. If you want to * Deinitializes the decoder. Disables decoding and detaches the interrupt handler. If you want to
* re-enable decoding, call init() again. * re-enable decoding, call init() again.
*/ */
static void deinit(); static void deinit();
/** /**
* Tells wether a signal is being received. If a compatible signal is detected within the time out, isReceiving returns true. * Tells wether a signal is being received. If a compatible signal is detected within the time out, isReceiving returns true.
* Since it makes no sense to transmit while another transmitter is active, it's best to wait for isReceiving() to false. * Since it makes no sense to transmit while another transmitter is active, it's best to wait for isReceiving() to false.
* By default it waits for 150ms, in which a (relative slow) KaKu signal can be broadcasted three times. * By default it waits for 150ms, in which a (relative slow) KaKu signal can be broadcasted three times.
* *
* Note: isReceiving() depends on interrupts enabled. Thus, when disabled()'ed, or when interrupts are disabled (as is * Note: isReceiving() depends on interrupts enabled. Thus, when disabled()'ed, or when interrupts are disabled (as is
* the case in the callback), isReceiving() will not work properly. * the case in the callback), isReceiving() will not work properly.
* *
* @param waitMillis number of milliseconds to monitor for signal. * @param waitMillis number of milliseconds to monitor for signal.
* @return boolean If after waitMillis no signal was being processed, returns false. If before expiration a signal was being processed, returns true. * @return boolean If after waitMillis no signal was being processed, returns false. If before expiration a signal was being processed, returns true.
*/ */
static boolean isReceiving(int waitMillis = 150); static boolean isReceiving(int waitMillis = 150);
static void interruptHandler(); static void interruptHandler();
private: private:
static int8_t _interrupt; // Radio input interrupt static int8_t _interrupt; // Radio input interrupt
volatile static int8_t _state; // State of decoding process. There are 49 states, 1 for "waiting for signal" and 48 for decoding the 48 edges in a valid code. volatile static int8_t _state; // State of decoding process. There are 49 states, 1 for "waiting for signal" and 48 for decoding the 48 edges in a valid code.
static byte _minRepeats; static byte _minRepeats;
static RemoteReceiverCallBack _callback; static RemoteReceiverCallBack _callback;
static boolean _inCallback; // When true, the callback function is being executed; prevents re-entrance. static boolean _inCallback; // When true, the callback function is being executed; prevents re-entrance.
static boolean _enabled; // If true, monitoring and decoding is enabled. If false, interruptHandler will return immediately. static boolean _enabled; // If true, monitoring and decoding is enabled. If false, interruptHandler will return immediately.
}; };
#endif #endif
+305 -305
View File
@@ -1,305 +1,305 @@
/* /*
* RemoteSwitch library v2.3.0 (20121229) made by Randy Simons http://randysimons.nl/ * RemoteSwitch library v2.3.0 (20121229) made by Randy Simons http://randysimons.nl/
* See RemoteTransmitter.h for details. * See RemoteTransmitter.h for details.
* *
* License: GPLv3. See license.txt * License: GPLv3. See license.txt
*/ */
#include "RemoteTransmitter.h" #include "RemoteTransmitter.h"
/************ /************
* RemoteTransmitter * RemoteTransmitter
************/ ************/
RemoteTransmitter::RemoteTransmitter(byte pin, unsigned int periodusec, byte repeats) { RemoteTransmitter::RemoteTransmitter(byte pin, unsigned int periodusec, byte repeats) {
_pin=pin; _pin=pin;
_periodusec=periodusec; _periodusec=periodusec;
_repeats=repeats; _repeats=repeats;
pinMode(_pin, OUTPUT); pinMode(_pin, OUTPUT);
} }
unsigned long RemoteTransmitter::encodeTelegram(byte trits[]) { unsigned long RemoteTransmitter::encodeTelegram(byte trits[]) {
unsigned long data = 0; unsigned long data = 0;
// Encode data // Encode data
for (byte i=0;i<12;i++) { for (byte i=0;i<12;i++) {
data*=3; data*=3;
data+=trits[i]; data+=trits[i];
} }
// Encode period duration // Encode period duration
data |= (unsigned long)_periodusec << 23; data |= (unsigned long)_periodusec << 23;
// Encode repeats // Encode repeats
data |= (unsigned long)_repeats << 20; data |= (unsigned long)_repeats << 20;
return data; return data;
} }
void RemoteTransmitter::sendTelegram(byte trits[]) { void RemoteTransmitter::sendTelegram(byte trits[]) {
sendTelegram(encodeTelegram(trits),_pin); sendTelegram(encodeTelegram(trits),_pin);
} }
/** /**
* Format data: * Format data:
* pppppppp|prrrdddd|dddddddd|dddddddd (32 bit) * pppppppp|prrrdddd|dddddddd|dddddddd (32 bit)
* p = perioud (9 bit unsigned int * p = perioud (9 bit unsigned int
* r = repeats as 2log. Thus, if r = 3, then signal is sent 2^3=8 times * r = repeats as 2log. Thus, if r = 3, then signal is sent 2^3=8 times
* d = data * d = data
*/ */
void RemoteTransmitter::sendTelegram(unsigned long data, byte pin) { void RemoteTransmitter::sendTelegram(unsigned long data, byte pin) {
unsigned int periodusec = (unsigned long)data >> 23; unsigned int periodusec = (unsigned long)data >> 23;
byte repeats = ((unsigned long)data >> 20) & B111; byte repeats = ((unsigned long)data >> 20) & B111;
sendCode(pin, data, periodusec, repeats); sendCode(pin, data, periodusec, repeats);
} }
void RemoteTransmitter::sendCode(byte pin, unsigned long code, unsigned int periodusec, byte repeats) { void RemoteTransmitter::sendCode(byte pin, unsigned long code, unsigned int periodusec, byte repeats) {
code &= 0xfffff; // Truncate to 20 bit ; code &= 0xfffff; // Truncate to 20 bit ;
// Convert the base3-code to base4, to avoid lengthy calculations when transmitting.. Messes op timings. // Convert the base3-code to base4, to avoid lengthy calculations when transmitting.. Messes op timings.
// Also note this swaps endianess in the process. The MSB must be transmitted first, but is converted to // Also note this swaps endianess in the process. The MSB must be transmitted first, but is converted to
// LSB here. This is easier when actually transmitting later on. // LSB here. This is easier when actually transmitting later on.
unsigned long dataBase4 = 0; unsigned long dataBase4 = 0;
for (byte i=0; i<12; i++) { for (byte i=0; i<12; i++) {
dataBase4<<=2; dataBase4<<=2;
dataBase4|=(code%3); dataBase4|=(code%3);
code/=3; code/=3;
} }
repeats = 1 << (repeats & B111); // repeats := 2^repeats; repeats = 1 << (repeats & B111); // repeats := 2^repeats;
for (byte j=0;j<repeats;j++) { for (byte j=0;j<repeats;j++) {
// Sent one telegram // Sent one telegram
// Recycle code as working var to save memory // Recycle code as working var to save memory
code=dataBase4; code=dataBase4;
for (byte i=0; i<12; i++) { for (byte i=0; i<12; i++) {
switch (code & B11) { switch (code & B11) {
case 0: case 0:
digitalWrite(pin, HIGH); digitalWrite(pin, HIGH);
delayMicroseconds(periodusec); delayMicroseconds(periodusec);
digitalWrite(pin, LOW); digitalWrite(pin, LOW);
delayMicroseconds(periodusec*3); delayMicroseconds(periodusec*3);
digitalWrite(pin, HIGH); digitalWrite(pin, HIGH);
delayMicroseconds(periodusec); delayMicroseconds(periodusec);
digitalWrite(pin, LOW); digitalWrite(pin, LOW);
delayMicroseconds(periodusec*3); delayMicroseconds(periodusec*3);
break; break;
case 1: case 1:
digitalWrite(pin, HIGH); digitalWrite(pin, HIGH);
delayMicroseconds(periodusec*3); delayMicroseconds(periodusec*3);
digitalWrite(pin, LOW); digitalWrite(pin, LOW);
delayMicroseconds(periodusec); delayMicroseconds(periodusec);
digitalWrite(pin, HIGH); digitalWrite(pin, HIGH);
delayMicroseconds(periodusec*3); delayMicroseconds(periodusec*3);
digitalWrite(pin, LOW); digitalWrite(pin, LOW);
delayMicroseconds(periodusec); delayMicroseconds(periodusec);
break; break;
case 2: // KA: X or float case 2: // KA: X or float
digitalWrite(pin, HIGH); digitalWrite(pin, HIGH);
delayMicroseconds(periodusec); delayMicroseconds(periodusec);
digitalWrite(pin, LOW); digitalWrite(pin, LOW);
delayMicroseconds(periodusec*3); delayMicroseconds(periodusec*3);
digitalWrite(pin, HIGH); digitalWrite(pin, HIGH);
delayMicroseconds(periodusec*3); delayMicroseconds(periodusec*3);
digitalWrite(pin, LOW); digitalWrite(pin, LOW);
delayMicroseconds(periodusec); delayMicroseconds(periodusec);
break; break;
} }
// Next trit // Next trit
code>>=2; code>>=2;
} }
// Send termination/synchronization-signal. Total length: 32 periods // Send termination/synchronization-signal. Total length: 32 periods
digitalWrite(pin, HIGH); digitalWrite(pin, HIGH);
delayMicroseconds(periodusec); delayMicroseconds(periodusec);
digitalWrite(pin, LOW); digitalWrite(pin, LOW);
delayMicroseconds(periodusec*31); delayMicroseconds(periodusec*31);
} }
} }
boolean RemoteTransmitter::isSameCode(unsigned long encodedTelegram, unsigned long receivedData) { boolean RemoteTransmitter::isSameCode(unsigned long encodedTelegram, unsigned long receivedData) {
return (receivedData==(encodedTelegram & 0xFFFFF)); // compare the 20 LSB's return (receivedData==(encodedTelegram & 0xFFFFF)); // compare the 20 LSB's
} }
/************ /************
* ActionTransmitter * ActionTransmitter
************/ ************/
ActionTransmitter::ActionTransmitter(byte pin, unsigned int periodusec, byte repeats) : RemoteTransmitter(pin,periodusec,repeats) { ActionTransmitter::ActionTransmitter(byte pin, unsigned int periodusec, byte repeats) : RemoteTransmitter(pin,periodusec,repeats) {
// Call constructor // Call constructor
} }
void ActionTransmitter::sendSignal(byte systemCode, char device, boolean on) { void ActionTransmitter::sendSignal(byte systemCode, char device, boolean on) {
sendTelegram(getTelegram(systemCode,device,on), _pin); sendTelegram(getTelegram(systemCode,device,on), _pin);
} }
unsigned long ActionTransmitter::getTelegram(byte systemCode, char device, boolean on) { unsigned long ActionTransmitter::getTelegram(byte systemCode, char device, boolean on) {
byte trits[12]; byte trits[12];
device-=65; device-=65;
for (byte i=0; i<5; i++) { for (byte i=0; i<5; i++) {
// Trits 0-4 contain address (2^5=32 addresses) // Trits 0-4 contain address (2^5=32 addresses)
trits[i]=(systemCode & 1)?1:2; trits[i]=(systemCode & 1)?1:2;
systemCode>>=1; systemCode>>=1;
// Trits 5-9 contain device. Only one trit has value 0, others have 2 (float)! // Trits 5-9 contain device. Only one trit has value 0, others have 2 (float)!
trits[i+5]=(i==device?0:2); trits[i+5]=(i==device?0:2);
} }
// Switch on or off // Switch on or off
trits[10]=(!on?0:2); trits[10]=(!on?0:2);
trits[11]=(on?0:2); trits[11]=(on?0:2);
return encodeTelegram(trits); return encodeTelegram(trits);
} }
/************ /************
* BlokkerTransmitter * BlokkerTransmitter
************/ ************/
BlokkerTransmitter::BlokkerTransmitter(byte pin, unsigned int periodusec, byte repeats) : RemoteTransmitter(pin,periodusec,repeats) { BlokkerTransmitter::BlokkerTransmitter(byte pin, unsigned int periodusec, byte repeats) : RemoteTransmitter(pin,periodusec,repeats) {
// Call constructor // Call constructor
} }
void BlokkerTransmitter::sendSignal(byte device, boolean on) { void BlokkerTransmitter::sendSignal(byte device, boolean on) {
sendTelegram(getTelegram(device,on), _pin); sendTelegram(getTelegram(device,on), _pin);
} }
unsigned long BlokkerTransmitter::getTelegram(byte device, boolean on) { unsigned long BlokkerTransmitter::getTelegram(byte device, boolean on) {
byte trits[12]={0}; byte trits[12]={0};
device--; device--;
for (byte i=1; i<4; i++) { for (byte i=1; i<4; i++) {
// Trits 1-3 contain device // Trits 1-3 contain device
trits[i]=(device & 1)?0:1; trits[i]=(device & 1)?0:1;
device>>=1; device>>=1;
} }
// Switch on or off // Switch on or off
trits[8]=(on?1:0); trits[8]=(on?1:0);
return encodeTelegram(trits); return encodeTelegram(trits);
} }
/************ /************
* KaKuTransmitter * KaKuTransmitter
************/ ************/
KaKuTransmitter::KaKuTransmitter(byte pin, unsigned int periodusec, byte repeats) : RemoteTransmitter(pin,periodusec,repeats) { KaKuTransmitter::KaKuTransmitter(byte pin, unsigned int periodusec, byte repeats) : RemoteTransmitter(pin,periodusec,repeats) {
// Call constructor // Call constructor
} }
void KaKuTransmitter::sendSignal(char address, byte device, boolean on) { void KaKuTransmitter::sendSignal(char address, byte device, boolean on) {
sendTelegram(getTelegram(address, device, on), _pin); sendTelegram(getTelegram(address, device, on), _pin);
} }
unsigned long KaKuTransmitter::getTelegram(char address, byte device, boolean on) { unsigned long KaKuTransmitter::getTelegram(char address, byte device, boolean on) {
byte trits[12]; byte trits[12];
address-=65; address-=65;
device-=1; device-=1;
for (byte i=0; i<4; i++) { for (byte i=0; i<4; i++) {
// Trits 0-3 contain address (2^4 = 16 addresses) // Trits 0-3 contain address (2^4 = 16 addresses)
trits[i]=(address & 1)?2:0; trits[i]=(address & 1)?2:0;
address>>=1; address>>=1;
// Trits 4-8 contain device (2^4 = 16 addresses) // Trits 4-8 contain device (2^4 = 16 addresses)
trits[i+4]=(device & 1)?2:0; trits[i+4]=(device & 1)?2:0;
device>>=1; device>>=1;
} }
// Trits 8-10 seem to be fixed // Trits 8-10 seem to be fixed
trits[8]=0; trits[8]=0;
trits[9]=2; trits[9]=2;
trits[10]=2; trits[10]=2;
// Switch on or off // Switch on or off
trits[11]=(on?2:0); trits[11]=(on?2:0);
return encodeTelegram(trits); return encodeTelegram(trits);
} }
void KaKuTransmitter::sendSignal(char address, byte group, byte device, boolean on) { void KaKuTransmitter::sendSignal(char address, byte group, byte device, boolean on) {
sendTelegram(getTelegram(address, group, on), _pin); sendTelegram(getTelegram(address, group, on), _pin);
} }
unsigned long KaKuTransmitter::getTelegram(char address, byte group, byte device, boolean on) { unsigned long KaKuTransmitter::getTelegram(char address, byte group, byte device, boolean on) {
byte trits[12], i; byte trits[12], i;
address-=65; address-=65;
group-=1; group-=1;
device-=1; device-=1;
// Address. M3E Pin A0-A3 // Address. M3E Pin A0-A3
for (i=0; i<4; i++) { for (i=0; i<4; i++) {
// Trits 0-3 contain address (2^4 = 16 addresses) // Trits 0-3 contain address (2^4 = 16 addresses)
trits[i]=(address & 1)?2:0; trits[i]=(address & 1)?2:0;
address>>=1; address>>=1;
} }
// Device. M3E Pin A4-A5 // Device. M3E Pin A4-A5
for (; i<6; i++) { for (; i<6; i++) {
trits[i]=(device & 1)?2:0; trits[i]=(device & 1)?2:0;
device>>=1; device>>=1;
} }
// Group. M3E Pin A6-A7 // Group. M3E Pin A6-A7
for (; i<8; i++) { for (; i<8; i++) {
trits[i]=(group & 1)?2:0; trits[i]=(group & 1)?2:0;
group>>=1; group>>=1;
} }
// Trits 8-10 are be fixed. M3E Pin A8/D0-A10/D2 // Trits 8-10 are be fixed. M3E Pin A8/D0-A10/D2
trits[8]=0; trits[8]=0;
trits[9]=2; trits[9]=2;
trits[10]=2; trits[10]=2;
// Switch on or off, M3E Pin A11/D3 // Switch on or off, M3E Pin A11/D3
trits[11]=(on?2:0); trits[11]=(on?2:0);
return encodeTelegram(trits); return encodeTelegram(trits);
} }
/************ /************
* ElroTransmitter * ElroTransmitter
************/ ************/
ElroTransmitter::ElroTransmitter(byte pin, unsigned int periodusec, byte repeats) : RemoteTransmitter(pin, periodusec, repeats) { ElroTransmitter::ElroTransmitter(byte pin, unsigned int periodusec, byte repeats) : RemoteTransmitter(pin, periodusec, repeats) {
//Call constructor //Call constructor
} }
void ElroTransmitter::sendSignal(byte systemCode, char device, boolean on) { void ElroTransmitter::sendSignal(byte systemCode, char device, boolean on) {
sendTelegram(getTelegram(systemCode, device, on), _pin); sendTelegram(getTelegram(systemCode, device, on), _pin);
} }
unsigned long ElroTransmitter::getTelegram(byte systemCode, char device, boolean on) { unsigned long ElroTransmitter::getTelegram(byte systemCode, char device, boolean on) {
byte trits[12]; byte trits[12];
device-=65; device-=65;
for (byte i=0; i<5; i++) { for (byte i=0; i<5; i++) {
//trits 0-4 contain address (2^5=32 addresses) //trits 0-4 contain address (2^5=32 addresses)
trits[i]=(systemCode & 1)?0:2; trits[i]=(systemCode & 1)?0:2;
systemCode>>=1; systemCode>>=1;
//trits 5-9 contain device. Only one trit has value 0, others have 2 (float)! //trits 5-9 contain device. Only one trit has value 0, others have 2 (float)!
trits[i+5]=(i==device?0:2); trits[i+5]=(i==device?0:2);
} }
//switch on or off //switch on or off
trits[10]=(on?0:2); trits[10]=(on?0:2);
trits[11]=(!on?0:2); trits[11]=(!on?0:2);
return encodeTelegram(trits); return encodeTelegram(trits);
} }
+249 -249
View File
@@ -1,249 +1,249 @@
/* /*
* RemoteSwitch library v2.3.0 (20121229) made by Randy Simons http://randysimons.nl/ * RemoteSwitch library v2.3.0 (20121229) made by Randy Simons http://randysimons.nl/
* *
* License: GPLv3. See license.txt * License: GPLv3. See license.txt
*/ */
#ifndef RemoteTransmitter_h #ifndef RemoteTransmitter_h
#define RemoteTransmitter_h #define RemoteTransmitter_h
#include <Arduino.h> #include <Arduino.h>
/** /**
* RemoteTransmitter provides a generic class for simulation of common RF remote controls, like the 'Klik aan Klik uit'-system * RemoteTransmitter provides a generic class for simulation of common RF remote controls, like the 'Klik aan Klik uit'-system
* (http://www.klikaanklikuit.nl/), used to remotely switch lights etc. * (http://www.klikaanklikuit.nl/), used to remotely switch lights etc.
* *
* Many of these remotes seem to use a 433MHz SAW resonator and one of these chips: LP801B, HX2262, PT2262, M3E. * Many of these remotes seem to use a 433MHz SAW resonator and one of these chips: LP801B, HX2262, PT2262, M3E.
* Datasheet for the HX2262/PT2262 ICs: * Datasheet for the HX2262/PT2262 ICs:
* http://www.princeton.com.tw/downloadprocess/downloadfile.asp?mydownload=PT2262_1.pdf * http://www.princeton.com.tw/downloadprocess/downloadfile.asp?mydownload=PT2262_1.pdf
* *
* Hardware required for this library: a 433MHz/434MHz SAW oscillator transmitter, e.g. * Hardware required for this library: a 433MHz/434MHz SAW oscillator transmitter, e.g.
* http://www.sparkfun.com/products/10534 * http://www.sparkfun.com/products/10534
* http://www.conrad.nl/goto/?product=130428 * http://www.conrad.nl/goto/?product=130428
* *
* Notes: * Notes:
* - Since these chips use (and send!) tri-state inputs (low, high and floating) I use 'trits' instead of 'bits', * - Since these chips use (and send!) tri-state inputs (low, high and floating) I use 'trits' instead of 'bits',
* when appropriate. * when appropriate.
* - I measured the period lengths with a scope. Thus: they work for my remotes, but may fail for yours... * - I measured the period lengths with a scope. Thus: they work for my remotes, but may fail for yours...
* A better way would be to calculate the 'target'-timings using the datasheets and the resistor-values on the remotes. * A better way would be to calculate the 'target'-timings using the datasheets and the resistor-values on the remotes.
*/ */
class RemoteTransmitter { class RemoteTransmitter {
public: public:
/** /**
* Constructor. * Constructor.
* *
* To obtain the correct period length, an oscilloscope is convenient, but you can also read the * To obtain the correct period length, an oscilloscope is convenient, but you can also read the
* datasheet of the transmitter, measure the resistor for the oscillator and calculate the frequency. * datasheet of the transmitter, measure the resistor for the oscillator and calculate the frequency.
* *
* @param pin output pin on Arduino to which the transmitter is connected * @param pin output pin on Arduino to which the transmitter is connected
* @param periodusec [0..511] Duration of one period, in microseconds. A trit is 6 periods. * @param periodusec [0..511] Duration of one period, in microseconds. A trit is 6 periods.
* @param repeats [0..7] The 2log-Number of times the signal is repeated. The actual number of repeats will be 2^repeats. 2 would be bare minimum, 4 seems robust. * @param repeats [0..7] The 2log-Number of times the signal is repeated. The actual number of repeats will be 2^repeats. 2 would be bare minimum, 4 seems robust.
*/ */
RemoteTransmitter(byte pin, unsigned int periodusec, byte repeats); RemoteTransmitter(byte pin, unsigned int periodusec, byte repeats);
/** /**
* Encodes the data base on the current object and the given trits. The data can be reused, e.g. * Encodes the data base on the current object and the given trits. The data can be reused, e.g.
* for use with the static version of sendTelegram, so you won't need to instantiate costly objects! * for use with the static version of sendTelegram, so you won't need to instantiate costly objects!
* *
* @return The data suited for use with RemoteTransmitter::sendTelegram. * @return The data suited for use with RemoteTransmitter::sendTelegram.
*/ */
unsigned long encodeTelegram(byte trits[]); unsigned long encodeTelegram(byte trits[]);
/** /**
* Send a telegram, including synchronization-part. * Send a telegram, including synchronization-part.
* *
* @param trits Array of size 12. "trits" should be either 0, 1 or 2, where 2 indicates "float" * @param trits Array of size 12. "trits" should be either 0, 1 or 2, where 2 indicates "float"
*/ */
void sendTelegram(byte trits[]); void sendTelegram(byte trits[]);
/** /**
* Send a telegram, including synchronization-part. The data-param encodes the period duration, number of repeats and the actual data. * Send a telegram, including synchronization-part. The data-param encodes the period duration, number of repeats and the actual data.
* Note: static method, which allows for use in low-mem situations. * Note: static method, which allows for use in low-mem situations.
* *
* Format data: * Format data:
* pppppppp|prrrdddd|dddddddd|dddddddd (32 bit) * pppppppp|prrrdddd|dddddddd|dddddddd (32 bit)
* p = period (9 bit unsigned integer) * p = period (9 bit unsigned integer)
* r = repeats as 2log. Thus, if r = 3, then signal is sent 2^3=8 times * r = repeats as 2log. Thus, if r = 3, then signal is sent 2^3=8 times
* d = data * d = data
* *
* @param data data, period and repeats. * @param data data, period and repeats.
* @param pin Pin number of the transmitter. * @param pin Pin number of the transmitter.
*/ */
static void sendTelegram(unsigned long data, byte pin); static void sendTelegram(unsigned long data, byte pin);
/** /**
* The complement of RemoteReceiver. Send a telegram with specified code as data. * The complement of RemoteReceiver. Send a telegram with specified code as data.
* *
* Note: static method, which allows for use in low-mem situations. * Note: static method, which allows for use in low-mem situations.
* *
* @param pin output pin on Arduino to which the transmitter is connected * @param pin output pin on Arduino to which the transmitter is connected
* @param periodusec [0..511] Duration of one period, in microseconds. A trit is 6 periods. * @param periodusec [0..511] Duration of one period, in microseconds. A trit is 6 periods.
* @param repeats [0..7] The 2log-Number of times the signal is repeated. The actual number of repeats will be 2^repeats. 2 would be bare minimum, 4 seems robust. * @param repeats [0..7] The 2log-Number of times the signal is repeated. The actual number of repeats will be 2^repeats. 2 would be bare minimum, 4 seems robust.
* @param code The code to transmit. Note: only the first 20 bits are used, the rest is ignored. Also see sendTelegram. * @param code The code to transmit. Note: only the first 20 bits are used, the rest is ignored. Also see sendTelegram.
*/ */
static void sendCode(byte pin, unsigned long code, unsigned int periodusec, byte repeats); static void sendCode(byte pin, unsigned long code, unsigned int periodusec, byte repeats);
/** /**
* Compares the data received with RemoteReceive with the data obtained by one of the getTelegram-functions. * Compares the data received with RemoteReceive with the data obtained by one of the getTelegram-functions.
* Period duration and repetitions are ignored by this function; only the data-payload is compared. * Period duration and repetitions are ignored by this function; only the data-payload is compared.
* *
* @return true, if the codes are identical (the 20 least significant bits match) * @return true, if the codes are identical (the 20 least significant bits match)
*/ */
static boolean isSameCode(unsigned long encodedTelegram, unsigned long receivedData); static boolean isSameCode(unsigned long encodedTelegram, unsigned long receivedData);
protected: protected:
byte _pin; // Transmitter output pin byte _pin; // Transmitter output pin
unsigned int _periodusec; // Oscillator period in microseconds unsigned int _periodusec; // Oscillator period in microseconds
byte _repeats; // Number over repetitions of one telegram byte _repeats; // Number over repetitions of one telegram
}; };
/** /**
* ActionTransmitter simulates a remote, as sold in the Dutch 'Action' stores. But there are many similar systems on the market. * ActionTransmitter simulates a remote, as sold in the Dutch 'Action' stores. But there are many similar systems on the market.
* If your remote has setting for 5 address bits, and can control 5 devices on or off, then you can try to use the ActionTransmitter. * If your remote has setting for 5 address bits, and can control 5 devices on or off, then you can try to use the ActionTransmitter.
* Otherwise you may have luck with the ElroTransmitter, which is similar. * Otherwise you may have luck with the ElroTransmitter, which is similar.
*/ */
class ActionTransmitter: RemoteTransmitter { class ActionTransmitter: RemoteTransmitter {
public: public:
/** /**
* Constructor * Constructor
* *
* @param pin output pin on Arduino to which the transmitter is connected * @param pin output pin on Arduino to which the transmitter is connected
* @param periodsec Duration of one period, in microseconds. Default is 190usec * @param periodsec Duration of one period, in microseconds. Default is 190usec
* @param repeats [0..7] The 2log-Number of times the signal is repeated. * @param repeats [0..7] The 2log-Number of times the signal is repeated.
* @see RemoteTransmitter * @see RemoteTransmitter
*/ */
ActionTransmitter(byte pin, unsigned int periodusec=190, byte repeats=4); ActionTransmitter(byte pin, unsigned int periodusec=190, byte repeats=4);
/** /**
* Send a on or off signal to a device. * Send a on or off signal to a device.
* *
* @param systemCode 5-bit address (dip switches in remote). Range [0..31] * @param systemCode 5-bit address (dip switches in remote). Range [0..31]
* @param device Device to switch. Range: [A..E] (case sensitive!) * @param device Device to switch. Range: [A..E] (case sensitive!)
* @param on True, to switch on. False to switch off, * @param on True, to switch on. False to switch off,
*/ */
void sendSignal(byte systemCode, char device, boolean on); void sendSignal(byte systemCode, char device, boolean on);
/** /**
* Generates the telegram (data) which can be used for RemoteTransmitter::sendTelegram. * Generates the telegram (data) which can be used for RemoteTransmitter::sendTelegram.
* See sendSignal for details on the parameters * See sendSignal for details on the parameters
* *
* @return Encoded data, including repeats and period duration. * @return Encoded data, including repeats and period duration.
*/ */
unsigned long getTelegram(byte systemCode, char device, boolean on); unsigned long getTelegram(byte systemCode, char device, boolean on);
}; };
/** /**
* BlokkerTransmitter simulates a remote, as sold in the Dutch 'Blokker' stores. But there are many similar systems on the market. * BlokkerTransmitter simulates a remote, as sold in the Dutch 'Blokker' stores. But there are many similar systems on the market.
* These remotes have 4 on, 4 off buttons and a switch to switch between device 1-4 and 5-8. No further configuration * These remotes have 4 on, 4 off buttons and a switch to switch between device 1-4 and 5-8. No further configuration
* possible. * possible.
*/ */
class BlokkerTransmitter: RemoteTransmitter { class BlokkerTransmitter: RemoteTransmitter {
public: public:
/** /**
* Constructor * Constructor
* *
* @param pin output pin on Arduino to which the transmitter is connected * @param pin output pin on Arduino to which the transmitter is connected
* @param periodsec Duration of one period, in microseconds. Default is 307usec * @param periodsec Duration of one period, in microseconds. Default is 307usec
* @param repeats [0..7] The 2log-Number of times the signal is repeated. * @param repeats [0..7] The 2log-Number of times the signal is repeated.
* @see RemoteTransmitter * @see RemoteTransmitter
*/ */
BlokkerTransmitter(byte pin, unsigned int periodusec=230, byte repeats=4); BlokkerTransmitter(byte pin, unsigned int periodusec=230, byte repeats=4);
/** /**
* Send a on or off signal to a device. * Send a on or off signal to a device.
* *
* @param device Device to switch. Range: [1..8] * @param device Device to switch. Range: [1..8]
* @param on True, to switch on. False to switch off, * @param on True, to switch on. False to switch off,
*/ */
void sendSignal(byte device, boolean on); void sendSignal(byte device, boolean on);
/** /**
* @see RemoteTransmitter::getTelegram * @see RemoteTransmitter::getTelegram
*/ */
unsigned long getTelegram(byte device, boolean on); unsigned long getTelegram(byte device, boolean on);
}; };
/** /**
* KaKuTransmitter simulates a KlikAanKlikUit-remote, but there are many clones. * KaKuTransmitter simulates a KlikAanKlikUit-remote, but there are many clones.
* If your transmitter has a address dial with the characters A till P, you can try this class. * If your transmitter has a address dial with the characters A till P, you can try this class.
*/ */
class KaKuTransmitter: RemoteTransmitter { class KaKuTransmitter: RemoteTransmitter {
public: public:
/** /**
* Constructor * Constructor
* *
* @param pin output pin on Arduino to which the transmitter is connected * @param pin output pin on Arduino to which the transmitter is connected
* @param periodsec Duration of one period, in microseconds. Default is 375usec * @param periodsec Duration of one period, in microseconds. Default is 375usec
* @param repeats [0..7] The 2log-Number of times the signal is repeated. * @param repeats [0..7] The 2log-Number of times the signal is repeated.
* @see RemoteTransmitter * @see RemoteTransmitter
*/ */
KaKuTransmitter(byte pin, unsigned int periodusec=375, byte repeats=4); KaKuTransmitter(byte pin, unsigned int periodusec=375, byte repeats=4);
/** /**
* Send a on or off signal to a device. * Send a on or off signal to a device.
* *
* @param address address (dial switches in remote). Range [A..P] (case sensitive!) * @param address address (dial switches in remote). Range [A..P] (case sensitive!)
* @param group Group to switch. Range: [1..4] * @param group Group to switch. Range: [1..4]
* @param device Device to switch. Range: [1..4] * @param device Device to switch. Range: [1..4]
* @param on True, to switch on. False to switch off, * @param on True, to switch on. False to switch off,
*/ */
void sendSignal(char address, byte group, byte device, boolean on); void sendSignal(char address, byte group, byte device, boolean on);
/** /**
* Send a on or off signal to a device. * Send a on or off signal to a device.
* *
* @param address address (dip switches in remote). Range [A..P] (case sensitive!) * @param address address (dip switches in remote). Range [A..P] (case sensitive!)
* @param device device (dial switches in remote). Range [1..16] * @param device device (dial switches in remote). Range [1..16]
* @param on True, to switch on. False to switch off, * @param on True, to switch on. False to switch off,
*/ */
void sendSignal(char address, byte device, boolean on); void sendSignal(char address, byte device, boolean on);
/** /**
* @see RemoteTransmitter::getTelegram * @see RemoteTransmitter::getTelegram
*/ */
unsigned long getTelegram(char address, byte group, byte device, boolean on); unsigned long getTelegram(char address, byte group, byte device, boolean on);
/** /**
* @see RemoteTransmitter::getTelegram * @see RemoteTransmitter::getTelegram
*/ */
unsigned long getTelegram(char address, byte device, boolean on); unsigned long getTelegram(char address, byte device, boolean on);
}; };
/** /**
* ElroTransmitter simulates remotes of the Elro "Home Control" series * ElroTransmitter simulates remotes of the Elro "Home Control" series
* see http://www.elro.eu/en/m/products/category/home_automation/home_control * see http://www.elro.eu/en/m/products/category/home_automation/home_control
* There are are many similar systems on the market. If your remote has setting for 5 address bits, and can control * There are are many similar systems on the market. If your remote has setting for 5 address bits, and can control
* 4 devices on or off, then you can try to use the ElroTransmitter. Otherwise you may have luck with the * 4 devices on or off, then you can try to use the ElroTransmitter. Otherwise you may have luck with the
* ActionTransmitter, which is similar. * ActionTransmitter, which is similar.
*/ */
class ElroTransmitter: RemoteTransmitter { class ElroTransmitter: RemoteTransmitter {
public: public:
/** /**
* Constructor * Constructor
* *
* @param pin output pin on Arduino to which the transmitter is connected * @param pin output pin on Arduino to which the transmitter is connected
* @param periodsec Duration of one period, in microseconds. Default is 320usec * @param periodsec Duration of one period, in microseconds. Default is 320usec
* @param repeats [0..7] The 2log-Number of times the signal is repeated. * @param repeats [0..7] The 2log-Number of times the signal is repeated.
* @see RemoteSwitch * @see RemoteSwitch
*/ */
ElroTransmitter(byte pin, unsigned int periodusec=320, byte repeats=4); ElroTransmitter(byte pin, unsigned int periodusec=320, byte repeats=4);
/** /**
* Send a on or off signal to a device. * Send a on or off signal to a device.
* *
* @param systemCode 5-bit address (dip switches in remote). Range [0..31] * @param systemCode 5-bit address (dip switches in remote). Range [0..31]
* @param device Device to switch. Range: [A..D] (case sensitive!) * @param device Device to switch. Range: [A..D] (case sensitive!)
* @param on True, to switch on. False to switch off, * @param on True, to switch on. False to switch off,
*/ */
void sendSignal(byte systemCode, char device, boolean on); void sendSignal(byte systemCode, char device, boolean on);
/** /**
* Generates the telegram (data) which can be used for RemoteSwitch::sendTelegram. * Generates the telegram (data) which can be used for RemoteSwitch::sendTelegram.
* See sendSignal for details on the parameters * See sendSignal for details on the parameters
* *
* @return Encoded data, including repeats and period duration. * @return Encoded data, including repeats and period duration.
*/ */
unsigned long getTelegram(byte systemCode, char device, boolean on); unsigned long getTelegram(byte systemCode, char device, boolean on);
}; };
#endif #endif
@@ -1,63 +1,63 @@
/* /*
* Demo for RF remote switch transmitter. * Demo for RF remote switch transmitter.
* For details, see RemoteTransmitter.h! * For details, see RemoteTransmitter.h!
* *
* This sketch switches some devices on and off in a loop. * This sketch switches some devices on and off in a loop.
* *
* Setup: * Setup:
* - Connect a 433MHz transmitter to digital pin 11. * - Connect a 433MHz transmitter to digital pin 11.
*/ */
#include <RemoteTransmitter.h> #include <RemoteTransmitter.h>
// Intantiate a new ActionTransmitter remote, use pin 11 // Intantiate a new ActionTransmitter remote, use pin 11
ActionTransmitter actionTransmitter(11); ActionTransmitter actionTransmitter(11);
// Intantiate a new KaKuTransmitter remote, also use pin 11 (same transmitter!) // Intantiate a new KaKuTransmitter remote, also use pin 11 (same transmitter!)
KaKuTransmitter kaKuTransmitter(11); KaKuTransmitter kaKuTransmitter(11);
// Intantiate a new Blokker remote, also use pin 11 (same transmitter!) // Intantiate a new Blokker remote, also use pin 11 (same transmitter!)
BlokkerTransmitter blokkerTransmitter(11); BlokkerTransmitter blokkerTransmitter(11);
// Intantiate a new Elro remote, also use pin 11 (same transmitter!) // Intantiate a new Elro remote, also use pin 11 (same transmitter!)
ElroTransmitter elroTransmitter(11); ElroTransmitter elroTransmitter(11);
void setup() { void setup() {
} }
void loop() { void loop() {
// Switch off KaKu-device 10 on address M // Switch off KaKu-device 10 on address M
kaKuTransmitter.sendSignal('M',10,false); kaKuTransmitter.sendSignal('M',10,false);
// Switch on Action-device B on system code 1. // Switch on Action-device B on system code 1.
actionTransmitter.sendSignal(1,'B',true); actionTransmitter.sendSignal(1,'B',true);
// Switch on Blokker-device 7. // Switch on Blokker-device 7.
blokkerTransmitter.sendSignal(7,true); blokkerTransmitter.sendSignal(7,true);
// Switch on Elro-device C on system code 1. // Switch on Elro-device C on system code 1.
elroTransmitter.sendSignal(1,'C',true); elroTransmitter.sendSignal(1,'C',true);
// Wait 2 seconds // Wait 2 seconds
delay(2000); delay(2000);
// Switch on KaKu-device 2 of group 3 on address M (which is the same as device 10 on address M!) // Switch on KaKu-device 2 of group 3 on address M (which is the same as device 10 on address M!)
kaKuTransmitter.sendSignal('M',3,2,true); kaKuTransmitter.sendSignal('M',3,2,true);
// Switch off Action-device B on system code 1. // Switch off Action-device B on system code 1.
actionTransmitter.sendSignal(1,'B',false); actionTransmitter.sendSignal(1,'B',false);
// Switch off Blokker-device 7. // Switch off Blokker-device 7.
blokkerTransmitter.sendSignal(7,false); blokkerTransmitter.sendSignal(7,false);
// Switch off Elro-device C on system code 1. // Switch off Elro-device C on system code 1.
elroTransmitter.sendSignal(1,'C',false); elroTransmitter.sendSignal(1,'C',false);
// Wait 4 seconds // Wait 4 seconds
delay(4000); delay(4000);
} }
+14 -14
View File
@@ -1,15 +1,15 @@
RemoteTransmitter KEYWORD1 RemoteTransmitter KEYWORD1
ActionTransmitter KEYWORD1 ActionTransmitter KEYWORD1
BlokkerTransmitter KEYWORD1 BlokkerTransmitter KEYWORD1
KaKuTransmitter KEYWORD1 KaKuTransmitter KEYWORD1
ElroTransmitter KEYWORD1 ElroTransmitter KEYWORD1
sendTelegram KEYWORD2 sendTelegram KEYWORD2
sendCode KEYWORD2 sendCode KEYWORD2
sendSignal KEYWORD2 sendSignal KEYWORD2
isSameCode KEYWORD2 isSameCode KEYWORD2
RemoteReceiver KEYWORD1 RemoteReceiver KEYWORD1
init KEYWORD2 init KEYWORD2
enable KEYWORD2 enable KEYWORD2
disable KEYWORD2 disable KEYWORD2
deinit KEYWORD2 deinit KEYWORD2
isReceiving KEYWORD2 isReceiving KEYWORD2
+88 -88
View File
@@ -1,89 +1,89 @@
#ifndef SimpleFIFO_h #ifndef SimpleFIFO_h
#define SimpleFIFO_h #define SimpleFIFO_h
/* /*
|| ||
|| @file SimpleFIFO.h || @file SimpleFIFO.h
|| @version 1.2 || @version 1.2
|| @author Alexander Brevig || @author Alexander Brevig
|| @contact alexanderbrevig@gmail.com || @contact alexanderbrevig@gmail.com
|| ||
|| @description || @description
|| | A simple FIFO class, mostly for primitive types but can be used with classes if assignment to int is allowed || | A simple FIFO class, mostly for primitive types but can be used with classes if assignment to int is allowed
|| | This FIFO is not dynamic, so be sure to choose an appropriate size for it || | This FIFO is not dynamic, so be sure to choose an appropriate size for it
|| # || #
|| ||
|| @license || @license
|| | Copyright (c) 2010 Alexander Brevig || | Copyright (c) 2010 Alexander Brevig
|| | This library is free software; you can redistribute it and/or || | This library is free software; you can redistribute it and/or
|| | modify it under the terms of the GNU Lesser General Public || | modify it under the terms of the GNU Lesser General Public
|| | License as published by the Free Software Foundation; version || | License as published by the Free Software Foundation; version
|| | 2.1 of the License. || | 2.1 of the License.
|| | || |
|| | This library is distributed in the hope that it will be useful, || | This library is distributed in the hope that it will be useful,
|| | but WITHOUT ANY WARRANTY; without even the implied warranty of || | but WITHOUT ANY WARRANTY; without even the implied warranty of
|| | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU || | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|| | Lesser General Public License for more details. || | Lesser General Public License for more details.
|| | || |
|| | You should have received a copy of the GNU Lesser General Public || | You should have received a copy of the GNU Lesser General Public
|| | License along with this library; if not, write to the Free Software || | License along with this library; if not, write to the Free Software
|| | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA || | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|| # || #
|| ||
*/ */
template<typename T, int rawSize> template<typename T, int rawSize>
class SimpleFIFO { class SimpleFIFO {
public: public:
const char size; //speculative feature, in case it's needed const char size; //speculative feature, in case it's needed
SimpleFIFO(); SimpleFIFO();
T dequeue(); //get next element T dequeue(); //get next element
bool enqueue( T element ); //add an element bool enqueue( T element ); //add an element
T peek() const; //get the next element without releasing it from the FIFO T peek() const; //get the next element without releasing it from the FIFO
void flush(); //[1.1] reset to default state void flush(); //[1.1] reset to default state
//how many elements are currently in the FIFO? //how many elements are currently in the FIFO?
char count() { return numberOfElements; } char count() { return numberOfElements; }
private: private:
#ifndef SimpleFIFO_NONVOLATILE #ifndef SimpleFIFO_NONVOLATILE
volatile char numberOfElements; volatile char numberOfElements;
volatile char nextIn; volatile char nextIn;
volatile char nextOut; volatile char nextOut;
volatile T raw[rawSize]; volatile T raw[rawSize];
#else #else
char numberOfElements; char numberOfElements;
char nextIn; char nextIn;
char nextOut; char nextOut;
T raw[rawSize]; T raw[rawSize];
#endif #endif
}; };
template<typename T, int rawSize> template<typename T, int rawSize>
SimpleFIFO<T,rawSize>::SimpleFIFO() : size(rawSize) { SimpleFIFO<T,rawSize>::SimpleFIFO() : size(rawSize) {
flush(); flush();
} }
template<typename T, int rawSize> template<typename T, int rawSize>
bool SimpleFIFO<T,rawSize>::enqueue( T element ) { bool SimpleFIFO<T,rawSize>::enqueue( T element ) {
if ( count() >= rawSize ) { return false; } if ( count() >= rawSize ) { return false; }
numberOfElements++; numberOfElements++;
nextIn %= size; nextIn %= size;
raw[nextIn] = element; raw[nextIn] = element;
nextIn++; //advance to next index nextIn++; //advance to next index
return true; return true;
} }
template<typename T, int rawSize> template<typename T, int rawSize>
T SimpleFIFO<T,rawSize>::dequeue() { T SimpleFIFO<T,rawSize>::dequeue() {
numberOfElements--; numberOfElements--;
nextOut %= size; nextOut %= size;
return raw[ nextOut++]; return raw[ nextOut++];
} }
template<typename T, int rawSize> template<typename T, int rawSize>
T SimpleFIFO<T,rawSize>::peek() const { T SimpleFIFO<T,rawSize>::peek() const {
return raw[ nextOut % size]; return raw[ nextOut % size];
} }
template<typename T, int rawSize> template<typename T, int rawSize>
void SimpleFIFO<T,rawSize>::flush() { void SimpleFIFO<T,rawSize>::flush() {
nextIn = nextOut = numberOfElements = 0; nextIn = nextOut = numberOfElements = 0;
} }
#endif #endif
@@ -1,27 +1,27 @@
#include <SimpleFIFO.h> #include <SimpleFIFO.h>
void setup() { void setup() {
Serial.begin(9600); Serial.begin(9600);
SimpleFIFO<int,10> sFIFO; //store 10 ints SimpleFIFO<int,10> sFIFO; //store 10 ints
sFIFO.enqueue(1); sFIFO.enqueue(1);
sFIFO.enqueue(2); sFIFO.enqueue(2);
sFIFO.enqueue(3); sFIFO.enqueue(3);
sFIFO.enqueue(4); sFIFO.enqueue(4);
sFIFO.enqueue(5); sFIFO.enqueue(5);
Serial.print(F("Peek: ")); Serial.print(F("Peek: "));
Serial.println(sFIFO.peek()); Serial.println(sFIFO.peek());
for (int i=0; i<sFIFO.count(); i++) { for (int i=0; i<sFIFO.count(); i++) {
Serial.print(F("Dequeue ")); Serial.print(F("Dequeue "));
Serial.println(sFIFO.dequeue()); Serial.println(sFIFO.dequeue());
} }
} }
void loop() { void loop() {
//nothing //nothing
} }
+80 -80
View File
@@ -1,80 +1,80 @@
/* DateStrings.cpp /* DateStrings.cpp
* Definitions for date strings for use with the Time library * Definitions for date strings for use with the Time library
* *
* No memory is consumed in the sketch if your code does not call any of the string methods * No memory is consumed in the sketch if your code does not call any of the string methods
* You can change the text of the strings, make sure the short strings are each exactly 3 characters * You can change the text of the strings, make sure the short strings are each exactly 3 characters
* the long strings can be any length up to the constant dt_MAX_STRING_LEN defined in Time.h * the long strings can be any length up to the constant dt_MAX_STRING_LEN defined in Time.h
* *
*/ */
#include <avr/pgmspace.h> #include <avr/pgmspace.h>
#include "Time.h" #include "Time.h"
// the short strings for each day or month must be exactly dt_SHORT_STR_LEN // the short strings for each day or month must be exactly dt_SHORT_STR_LEN
#define dt_SHORT_STR_LEN 3 // the length of short strings #define dt_SHORT_STR_LEN 3 // the length of short strings
static char buffer[dt_MAX_STRING_LEN+1]; // must be big enough for longest string and the terminating null static char buffer[dt_MAX_STRING_LEN+1]; // must be big enough for longest string and the terminating null
char monthStr1[] PROGMEM = "January"; char monthStr1[] PROGMEM = "January";
char monthStr2[] PROGMEM = "February"; char monthStr2[] PROGMEM = "February";
char monthStr3[] PROGMEM = "March"; char monthStr3[] PROGMEM = "March";
char monthStr4[] PROGMEM = "April"; char monthStr4[] PROGMEM = "April";
char monthStr5[] PROGMEM = "May"; char monthStr5[] PROGMEM = "May";
char monthStr6[] PROGMEM = "June"; char monthStr6[] PROGMEM = "June";
char monthStr7[] PROGMEM = "July"; char monthStr7[] PROGMEM = "July";
char monthStr8[] PROGMEM = "August"; char monthStr8[] PROGMEM = "August";
char monthStr9[] PROGMEM = "September"; char monthStr9[] PROGMEM = "September";
char monthStr10[] PROGMEM = "October"; char monthStr10[] PROGMEM = "October";
char monthStr11[] PROGMEM = "November"; char monthStr11[] PROGMEM = "November";
char monthStr12[] PROGMEM = "December"; char monthStr12[] PROGMEM = "December";
PGM_P monthNames_P[] PROGMEM = PGM_P monthNames_P[] PROGMEM =
{ {
"",monthStr1,monthStr2,monthStr3,monthStr4,monthStr5,monthStr6, "",monthStr1,monthStr2,monthStr3,monthStr4,monthStr5,monthStr6,
monthStr7,monthStr8,monthStr9,monthStr10,monthStr11,monthStr12 monthStr7,monthStr8,monthStr9,monthStr10,monthStr11,monthStr12
}; };
char monthShortNames_P[] PROGMEM = "ErrJanFebMarAprMayJunJulAugSepOctNovDec"; char monthShortNames_P[] PROGMEM = "ErrJanFebMarAprMayJunJulAugSepOctNovDec";
char dayStr0[] PROGMEM = "Err"; char dayStr0[] PROGMEM = "Err";
char dayStr1[] PROGMEM = "Sunday"; char dayStr1[] PROGMEM = "Sunday";
char dayStr2[] PROGMEM = "Monday"; char dayStr2[] PROGMEM = "Monday";
char dayStr3[] PROGMEM = "Tuesday"; char dayStr3[] PROGMEM = "Tuesday";
char dayStr4[] PROGMEM = "Wednesday"; char dayStr4[] PROGMEM = "Wednesday";
char dayStr5[] PROGMEM = "Thursday"; char dayStr5[] PROGMEM = "Thursday";
char dayStr6[] PROGMEM = "Friday"; char dayStr6[] PROGMEM = "Friday";
char dayStr7[] PROGMEM = "Saturday"; char dayStr7[] PROGMEM = "Saturday";
PGM_P dayNames_P[] PROGMEM = { dayStr0,dayStr1,dayStr2,dayStr3,dayStr4,dayStr5,dayStr6,dayStr7}; PGM_P dayNames_P[] PROGMEM = { dayStr0,dayStr1,dayStr2,dayStr3,dayStr4,dayStr5,dayStr6,dayStr7};
char dayShortNames_P[] PROGMEM = "ErrSunMonTueWedThrFriSat"; char dayShortNames_P[] PROGMEM = "ErrSunMonTueWedThrFriSat";
/* functions to return date strings */ /* functions to return date strings */
char* monthStr(uint8_t month) char* monthStr(uint8_t month)
{ {
strcpy_P(buffer, (PGM_P)pgm_read_word(&(monthNames_P[month]))); strcpy_P(buffer, (PGM_P)pgm_read_word(&(monthNames_P[month])));
return buffer; return buffer;
} }
char* monthShortStr(uint8_t month) char* monthShortStr(uint8_t month)
{ {
for (int i=0; i < dt_SHORT_STR_LEN; i++) for (int i=0; i < dt_SHORT_STR_LEN; i++)
buffer[i] = pgm_read_byte(&(monthShortNames_P[i+ (month*dt_SHORT_STR_LEN)])); buffer[i] = pgm_read_byte(&(monthShortNames_P[i+ (month*dt_SHORT_STR_LEN)]));
buffer[dt_SHORT_STR_LEN] = 0; buffer[dt_SHORT_STR_LEN] = 0;
return buffer; return buffer;
} }
char* dayStr(uint8_t day) char* dayStr(uint8_t day)
{ {
strcpy_P(buffer, (PGM_P)pgm_read_word(&(dayNames_P[day]))); strcpy_P(buffer, (PGM_P)pgm_read_word(&(dayNames_P[day])));
return buffer; return buffer;
} }
char* dayShortStr(uint8_t day) char* dayShortStr(uint8_t day)
{ {
uint8_t index = day*dt_SHORT_STR_LEN; uint8_t index = day*dt_SHORT_STR_LEN;
for (int i=0; i < dt_SHORT_STR_LEN; i++) for (int i=0; i < dt_SHORT_STR_LEN; i++)
buffer[i] = pgm_read_byte(&(dayShortNames_P[index + i])); buffer[i] = pgm_read_byte(&(dayShortNames_P[index + i]));
buffer[dt_SHORT_STR_LEN] = 0; buffer[dt_SHORT_STR_LEN] = 0;
return buffer; return buffer;
} }
+1 -1
View File
@@ -117,4 +117,4 @@ void write_n(int what, int how_many)
{ {
for( int i = 0; i < how_many; i++ ) for( int i = 0; i < how_many; i++ )
UdpBytewise.write(what); UdpBytewise.write(what);
} }
+1 -1
View File
@@ -44,4 +44,4 @@ void printDigits(int digits){
Serial.print('0'); Serial.print('0');
Serial.print(digits); Serial.print(digits);
} }
@@ -103,4 +103,4 @@ void showDuration(time_t duration){
Serial.print(duration); Serial.print(duration);
Serial.print(" second(s) "); Serial.print(" second(s) ");
} }
@@ -79,4 +79,4 @@ time_t processSyncMessage() {
} }
return 0; return 0;
} }
@@ -79,4 +79,4 @@ time_t requestSync()
Serial.print(TIME_REQUEST,BYTE); Serial.print(TIME_REQUEST,BYTE);
return 0; // the time will be sent later in response to serial mesg return 0; // the time will be sent later in response to serial mesg
} }
@@ -77,4 +77,4 @@ time_t requestSync()
Serial.print(TIME_REQUEST,BYTE); Serial.print(TIME_REQUEST,BYTE);
return 0; // the time will be sent later in response to serial mesg return 0; // the time will be sent later in response to serial mesg
} }
+130 -130
View File
@@ -1,131 +1,131 @@
Readme file for Arduino Time Library Readme file for Arduino Time Library
Time is a library that provides timekeeping functionality for Arduino. Time is a library that provides timekeeping functionality for Arduino.
The code is derived from the Playground DateTime library but is updated The code is derived from the Playground DateTime library but is updated
to provide an API that is more flexable and easier to use. to provide an API that is more flexable and easier to use.
A primary goal was to enable date and time functionality that can be used with A primary goal was to enable date and time functionality that can be used with
a variety of external time sources with minimum differences required in sketch logic. a variety of external time sources with minimum differences required in sketch logic.
Example sketches illustrate how similar sketch code can be used with: a Real Time Clock, Example sketches illustrate how similar sketch code can be used with: a Real Time Clock,
internet NTP time service, GPS time data, and Serial time messages from a computer internet NTP time service, GPS time data, and Serial time messages from a computer
for time synchronization. for time synchronization.
The functions available in the library include: The functions available in the library include:
hour(); // the hour now (0-23) hour(); // the hour now (0-23)
minute(); // the minute now (0-59) minute(); // the minute now (0-59)
second(); // the second now (0-59) second(); // the second now (0-59)
day(); // the day now (1-31) day(); // the day now (1-31)
weekday(); // day of the week, Sunday is day 0 weekday(); // day of the week, Sunday is day 0
month(); // the month now (1-12) month(); // the month now (1-12)
year(); // the full four digit year: (2009, 2010 etc) year(); // the full four digit year: (2009, 2010 etc)
there are also functions to return the hour in 12 hour format there are also functions to return the hour in 12 hour format
hourFormat12(); // the hour now in 12 hour format hourFormat12(); // the hour now in 12 hour format
isAM(); // returns true if time now is AM isAM(); // returns true if time now is AM
isPM(); // returns true if time now is PM isPM(); // returns true if time now is PM
now(); // returns the current time as seconds since Jan 1 1970 now(); // returns the current time as seconds since Jan 1 1970
The time and date functions can take an optional parameter for the time. This prevents The time and date functions can take an optional parameter for the time. This prevents
errors if the time rolls over between elements. For example, if a new minute begins errors if the time rolls over between elements. For example, if a new minute begins
between getting the minute and second, the values will be inconsistent. Using the between getting the minute and second, the values will be inconsistent. Using the
following functions eliminates this probglem following functions eliminates this probglem
time_t t = now(); // store the current time in time variable t time_t t = now(); // store the current time in time variable t
hour(t); // returns the hour for the given time t hour(t); // returns the hour for the given time t
minute(t); // returns the minute for the given time t minute(t); // returns the minute for the given time t
second(t); // returns the second for the given time t second(t); // returns the second for the given time t
day(t); // the day for the given time t day(t); // the day for the given time t
weekday(t); // day of the week for the given time t weekday(t); // day of the week for the given time t
month(t); // the month for the given time t month(t); // the month for the given time t
year(t); // the year for the given time t year(t); // the year for the given time t
Functions for managing the timer services are: Functions for managing the timer services are:
setTime(t); // set the system time to the give time t setTime(t); // set the system time to the give time t
setTime(hr,min,sec,day,mnth,yr); // alternative to above, yr is 2 or 4 digit yr (2010 or 10 sets year to 2010) setTime(hr,min,sec,day,mnth,yr); // alternative to above, yr is 2 or 4 digit yr (2010 or 10 sets year to 2010)
adjustTime(adjustment); // adjust system time by adding the adjustment value adjustTime(adjustment); // adjust system time by adding the adjustment value
timeStatus(); // indicates if time has been set and recently synchronized timeStatus(); // indicates if time has been set and recently synchronized
// returns one of the following enumerations: // returns one of the following enumerations:
timeNotSet // the time has never been set, the clock started at Jan 1 1970 timeNotSet // the time has never been set, the clock started at Jan 1 1970
timeNeedsSync // the time had been set but a sync attempt did not succeed timeNeedsSync // the time had been set but a sync attempt did not succeed
timeSet // the time is set and is synced timeSet // the time is set and is synced
Time and Date values are not valid if the status is timeNotSet. Otherwise values can be used but Time and Date values are not valid if the status is timeNotSet. Otherwise values can be used but
the returned time may have drifted if the status is timeNeedsSync. the returned time may have drifted if the status is timeNeedsSync.
setSyncProvider(getTimeFunction); // set the external time provider setSyncProvider(getTimeFunction); // set the external time provider
setSyncInterval(interval); // set the number of seconds between re-sync setSyncInterval(interval); // set the number of seconds between re-sync
There are many convenience macros in the time.h file for time constants and conversion of time units. There are many convenience macros in the time.h file for time constants and conversion of time units.
To use the library, copy the download to the Library directory. To use the library, copy the download to the Library directory.
The Time directory contains the Time library and some example sketches The Time directory contains the Time library and some example sketches
illustrating how the library can be used with various time sources: illustrating how the library can be used with various time sources:
- TimeSerial.pde shows Arduino as a clock without external hardware. - TimeSerial.pde shows Arduino as a clock without external hardware.
It is synchronized by time messages sent over the serial port. It is synchronized by time messages sent over the serial port.
A companion Processing sketch will automatically provide these messages A companion Processing sketch will automatically provide these messages
if it is running and connected to the Arduino serial port. if it is running and connected to the Arduino serial port.
- TimeSerialDateStrings.pde adds day and month name strings to the sketch above - TimeSerialDateStrings.pde adds day and month name strings to the sketch above
Short (3 character) and long strings are available to print the days of Short (3 character) and long strings are available to print the days of
the week and names of the months. the week and names of the months.
- TimeRTC uses a DS1307 real time clock to provide time synchronization. - TimeRTC uses a DS1307 real time clock to provide time synchronization.
A basic RTC library named DS1307RTC is included in the download. A basic RTC library named DS1307RTC is included in the download.
To run this sketch the DS1307RTC library must be installed. To run this sketch the DS1307RTC library must be installed.
- TimeRTCSet is similar to the above and adds the ability to set the Real Time Clock - TimeRTCSet is similar to the above and adds the ability to set the Real Time Clock
- TimeRTCLog demonstrates how to calculate the difference between times. - TimeRTCLog demonstrates how to calculate the difference between times.
It is a vary simple logger application that monitors events on digtial pins It is a vary simple logger application that monitors events on digtial pins
and prints (to the serial port) the time of an event and the time period since the previous event. and prints (to the serial port) the time of an event and the time period since the previous event.
- TimeNTP uses the Arduino Ethernet shield to access time using the internet NTP time service. - TimeNTP uses the Arduino Ethernet shield to access time using the internet NTP time service.
The NTP protocol uses UDP and the UdpBytewise library is required, see: The NTP protocol uses UDP and the UdpBytewise library is required, see:
http://bitbucket.org/bjoern/arduino_osc/src/14667490521f/libraries/Ethernet/ http://bitbucket.org/bjoern/arduino_osc/src/14667490521f/libraries/Ethernet/
-TimeGPS gets time from a GPS -TimeGPS gets time from a GPS
This requires the TinyGPS and NewSoftSerial libraries from Mikal Hart: This requires the TinyGPS and NewSoftSerial libraries from Mikal Hart:
http://arduiniana.org/libraries/TinyGPS and http://arduiniana.org/libraries/newsoftserial/ http://arduiniana.org/libraries/TinyGPS and http://arduiniana.org/libraries/newsoftserial/
Differences between this code and the playground DateTime library Differences between this code and the playground DateTime library
although the Time library is based on the DateTime codebase, the API has changed. although the Time library is based on the DateTime codebase, the API has changed.
Changes in the Time library API: Changes in the Time library API:
- time elements are functions returning int (they are variables in DateTime) - time elements are functions returning int (they are variables in DateTime)
- Years start from 1970 - Years start from 1970
- days of the week and months start from 1 (they start from 0 in DateTime) - days of the week and months start from 1 (they start from 0 in DateTime)
- DateStrings do not require a seperate library - DateStrings do not require a seperate library
- time elements can be accessed non-atomically (in DateTime they are always atomic) - time elements can be accessed non-atomically (in DateTime they are always atomic)
- function added to automatically sync time with extrnal source - function added to automatically sync time with extrnal source
- localTime and maketime parameters changed, localTime renamed to breakTime - localTime and maketime parameters changed, localTime renamed to breakTime
Technical notes: Technical notes:
Internal system time is based on the standard Unix time_t. Internal system time is based on the standard Unix time_t.
The value is the number of seconds since Jan 1 1970. The value is the number of seconds since Jan 1 1970.
System time begins at zero when the sketch starts. System time begins at zero when the sketch starts.
The internal time can be automatically synchronized at regular intervals to an external time source. The internal time can be automatically synchronized at regular intervals to an external time source.
This is enabled by calling the setSyncProvider(provider) function - the provider argument is This is enabled by calling the setSyncProvider(provider) function - the provider argument is
the address of a function that returns the current time as a time_t. the address of a function that returns the current time as a time_t.
See the sketches in the examples directory for usage. See the sketches in the examples directory for usage.
The default interval for re-syncing the time is 5 minutes but can be changed by calling the The default interval for re-syncing the time is 5 minutes but can be changed by calling the
setSyncInterval( interval) method to set the number of seconds between re-sync attempts. setSyncInterval( interval) method to set the number of seconds between re-sync attempts.
The Time library defines a structure for holding time elements that is a compact version of the C tm structure. The Time library defines a structure for holding time elements that is a compact version of the C tm structure.
All the members of the Arduino tm structure are bytes and the year is offset from 1970. All the members of the Arduino tm structure are bytes and the year is offset from 1970.
Convenience macros provide conversion to and from the Arduino format. Convenience macros provide conversion to and from the Arduino format.
Low level functions to convert between system time and individual time elements are provided: Low level functions to convert between system time and individual time elements are provided:
breakTime( time, &tm); // break time_t into elements stored in tm struct breakTime( time, &tm); // break time_t into elements stored in tm struct
makeTime( &tm); // return time_t from elements stored in tm struct makeTime( &tm); // return time_t from elements stored in tm struct
The DS1307RTC library included in the download provides an example of how a time provider The DS1307RTC library included in the download provides an example of how a time provider
can use the low level functions to interface with the Time library. can use the low level functions to interface with the Time library.
+478 -478
View File
@@ -1,478 +1,478 @@
// DHCP Library v0.3 - April 25, 2009 // DHCP Library v0.3 - April 25, 2009
// Author: Jordan Terrell - blog.jordanterrell.com // Author: Jordan Terrell - blog.jordanterrell.com
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include "Dhcp.h" #include "Dhcp.h"
#include "Arduino.h" #include "Arduino.h"
#include "utility/util.h" #include "utility/util.h"
int DhcpClass::beginWithDHCP(uint8_t *mac, unsigned long timeout, unsigned long responseTimeout) int DhcpClass::beginWithDHCP(uint8_t *mac, unsigned long timeout, unsigned long responseTimeout)
{ {
_dhcpLeaseTime=0; _dhcpLeaseTime=0;
_dhcpT1=0; _dhcpT1=0;
_dhcpT2=0; _dhcpT2=0;
_lastCheck=0; _lastCheck=0;
_timeout = timeout; _timeout = timeout;
_responseTimeout = responseTimeout; _responseTimeout = responseTimeout;
// zero out _dhcpMacAddr // zero out _dhcpMacAddr
memset(_dhcpMacAddr, 0, 6); memset(_dhcpMacAddr, 0, 6);
reset_DHCP_lease(); reset_DHCP_lease();
memcpy((void*)_dhcpMacAddr, (void*)mac, 6); memcpy((void*)_dhcpMacAddr, (void*)mac, 6);
_dhcp_state = STATE_DHCP_START; _dhcp_state = STATE_DHCP_START;
return request_DHCP_lease(); return request_DHCP_lease();
} }
void DhcpClass::reset_DHCP_lease(){ void DhcpClass::reset_DHCP_lease(){
// zero out _dhcpSubnetMask, _dhcpGatewayIp, _dhcpLocalIp, _dhcpDhcpServerIp, _dhcpDnsServerIp // zero out _dhcpSubnetMask, _dhcpGatewayIp, _dhcpLocalIp, _dhcpDhcpServerIp, _dhcpDnsServerIp
memset(_dhcpLocalIp, 0, 20); memset(_dhcpLocalIp, 0, 20);
} }
//return:0 on error, 1 if request is sent and response is received //return:0 on error, 1 if request is sent and response is received
int DhcpClass::request_DHCP_lease(){ int DhcpClass::request_DHCP_lease(){
uint8_t messageType = 0; uint8_t messageType = 0;
// Pick an initial transaction ID // Pick an initial transaction ID
_dhcpTransactionId = random(1UL, 2000UL); _dhcpTransactionId = random(1UL, 2000UL);
_dhcpInitialTransactionId = _dhcpTransactionId; _dhcpInitialTransactionId = _dhcpTransactionId;
_dhcpUdpSocket.stop(); _dhcpUdpSocket.stop();
if (_dhcpUdpSocket.begin(DHCP_CLIENT_PORT) == 0) if (_dhcpUdpSocket.begin(DHCP_CLIENT_PORT) == 0)
{ {
// Couldn't get a socket // Couldn't get a socket
return 0; return 0;
} }
presend_DHCP(); presend_DHCP();
int result = 0; int result = 0;
unsigned long startTime = millis(); unsigned long startTime = millis();
while(_dhcp_state != STATE_DHCP_LEASED) while(_dhcp_state != STATE_DHCP_LEASED)
{ {
if(_dhcp_state == STATE_DHCP_START) if(_dhcp_state == STATE_DHCP_START)
{ {
_dhcpTransactionId++; _dhcpTransactionId++;
send_DHCP_MESSAGE(DHCP_DISCOVER, ((millis() - startTime) / 1000)); send_DHCP_MESSAGE(DHCP_DISCOVER, ((millis() - startTime) / 1000));
_dhcp_state = STATE_DHCP_DISCOVER; _dhcp_state = STATE_DHCP_DISCOVER;
} }
else if(_dhcp_state == STATE_DHCP_REREQUEST){ else if(_dhcp_state == STATE_DHCP_REREQUEST){
_dhcpTransactionId++; _dhcpTransactionId++;
send_DHCP_MESSAGE(DHCP_REQUEST, ((millis() - startTime)/1000)); send_DHCP_MESSAGE(DHCP_REQUEST, ((millis() - startTime)/1000));
_dhcp_state = STATE_DHCP_REQUEST; _dhcp_state = STATE_DHCP_REQUEST;
} }
else if(_dhcp_state == STATE_DHCP_DISCOVER) else if(_dhcp_state == STATE_DHCP_DISCOVER)
{ {
uint32_t respId; uint32_t respId;
messageType = parseDHCPResponse(_responseTimeout, respId); messageType = parseDHCPResponse(_responseTimeout, respId);
if(messageType == DHCP_OFFER) if(messageType == DHCP_OFFER)
{ {
// We'll use the transaction ID that the offer came with, // We'll use the transaction ID that the offer came with,
// rather than the one we were up to // rather than the one we were up to
_dhcpTransactionId = respId; _dhcpTransactionId = respId;
send_DHCP_MESSAGE(DHCP_REQUEST, ((millis() - startTime) / 1000)); send_DHCP_MESSAGE(DHCP_REQUEST, ((millis() - startTime) / 1000));
_dhcp_state = STATE_DHCP_REQUEST; _dhcp_state = STATE_DHCP_REQUEST;
} }
} }
else if(_dhcp_state == STATE_DHCP_REQUEST) else if(_dhcp_state == STATE_DHCP_REQUEST)
{ {
uint32_t respId; uint32_t respId;
messageType = parseDHCPResponse(_responseTimeout, respId); messageType = parseDHCPResponse(_responseTimeout, respId);
if(messageType == DHCP_ACK) if(messageType == DHCP_ACK)
{ {
_dhcp_state = STATE_DHCP_LEASED; _dhcp_state = STATE_DHCP_LEASED;
result = 1; result = 1;
//use default lease time if we didn't get it //use default lease time if we didn't get it
if(_dhcpLeaseTime == 0){ if(_dhcpLeaseTime == 0){
_dhcpLeaseTime = DEFAULT_LEASE; _dhcpLeaseTime = DEFAULT_LEASE;
} }
//calculate T1 & T2 if we didn't get it //calculate T1 & T2 if we didn't get it
if(_dhcpT1 == 0){ if(_dhcpT1 == 0){
//T1 should be 50% of _dhcpLeaseTime //T1 should be 50% of _dhcpLeaseTime
_dhcpT1 = _dhcpLeaseTime >> 1; _dhcpT1 = _dhcpLeaseTime >> 1;
} }
if(_dhcpT2 == 0){ if(_dhcpT2 == 0){
//T2 should be 87.5% (7/8ths) of _dhcpLeaseTime //T2 should be 87.5% (7/8ths) of _dhcpLeaseTime
_dhcpT2 = _dhcpT1 << 1; _dhcpT2 = _dhcpT1 << 1;
} }
_renewInSec = _dhcpT1; _renewInSec = _dhcpT1;
_rebindInSec = _dhcpT2; _rebindInSec = _dhcpT2;
} }
else if(messageType == DHCP_NAK) else if(messageType == DHCP_NAK)
_dhcp_state = STATE_DHCP_START; _dhcp_state = STATE_DHCP_START;
} }
if(messageType == 255) if(messageType == 255)
{ {
messageType = 0; messageType = 0;
_dhcp_state = STATE_DHCP_START; _dhcp_state = STATE_DHCP_START;
} }
if(result != 1 && ((millis() - startTime) > _timeout)) if(result != 1 && ((millis() - startTime) > _timeout))
break; break;
} }
// We're done with the socket now // We're done with the socket now
_dhcpUdpSocket.stop(); _dhcpUdpSocket.stop();
_dhcpTransactionId++; _dhcpTransactionId++;
return result; return result;
} }
void DhcpClass::presend_DHCP() void DhcpClass::presend_DHCP()
{ {
} }
void DhcpClass::send_DHCP_MESSAGE(uint8_t messageType, uint16_t secondsElapsed) void DhcpClass::send_DHCP_MESSAGE(uint8_t messageType, uint16_t secondsElapsed)
{ {
uint8_t buffer[32]; uint8_t buffer[32];
memset(buffer, 0, 32); memset(buffer, 0, 32);
IPAddress dest_addr( 255, 255, 255, 255 ); // Broadcast address IPAddress dest_addr( 255, 255, 255, 255 ); // Broadcast address
if (-1 == _dhcpUdpSocket.beginPacket(dest_addr, DHCP_SERVER_PORT)) if (-1 == _dhcpUdpSocket.beginPacket(dest_addr, DHCP_SERVER_PORT))
{ {
// FIXME Need to return errors // FIXME Need to return errors
return; return;
} }
buffer[0] = DHCP_BOOTREQUEST; // op buffer[0] = DHCP_BOOTREQUEST; // op
buffer[1] = DHCP_HTYPE10MB; // htype buffer[1] = DHCP_HTYPE10MB; // htype
buffer[2] = DHCP_HLENETHERNET; // hlen buffer[2] = DHCP_HLENETHERNET; // hlen
buffer[3] = DHCP_HOPS; // hops buffer[3] = DHCP_HOPS; // hops
// xid // xid
unsigned long xid = htonl(_dhcpTransactionId); unsigned long xid = htonl(_dhcpTransactionId);
memcpy(buffer + 4, &(xid), 4); memcpy(buffer + 4, &(xid), 4);
// 8, 9 - seconds elapsed // 8, 9 - seconds elapsed
buffer[8] = ((secondsElapsed & 0xff00) >> 8); buffer[8] = ((secondsElapsed & 0xff00) >> 8);
buffer[9] = (secondsElapsed & 0x00ff); buffer[9] = (secondsElapsed & 0x00ff);
// flags // flags
unsigned short flags = htons(DHCP_FLAGSBROADCAST); unsigned short flags = htons(DHCP_FLAGSBROADCAST);
memcpy(buffer + 10, &(flags), 2); memcpy(buffer + 10, &(flags), 2);
// ciaddr: already zeroed // ciaddr: already zeroed
// yiaddr: already zeroed // yiaddr: already zeroed
// siaddr: already zeroed // siaddr: already zeroed
// giaddr: already zeroed // giaddr: already zeroed
//put data in W5100 transmit buffer //put data in W5100 transmit buffer
_dhcpUdpSocket.write(buffer, 28); _dhcpUdpSocket.write(buffer, 28);
memset(buffer, 0, 32); // clear local buffer memset(buffer, 0, 32); // clear local buffer
memcpy(buffer, _dhcpMacAddr, 6); // chaddr memcpy(buffer, _dhcpMacAddr, 6); // chaddr
//put data in W5100 transmit buffer //put data in W5100 transmit buffer
_dhcpUdpSocket.write(buffer, 16); _dhcpUdpSocket.write(buffer, 16);
memset(buffer, 0, 32); // clear local buffer memset(buffer, 0, 32); // clear local buffer
// leave zeroed out for sname && file // leave zeroed out for sname && file
// put in W5100 transmit buffer x 6 (192 bytes) // put in W5100 transmit buffer x 6 (192 bytes)
for(int i = 0; i < 6; i++) { for(int i = 0; i < 6; i++) {
_dhcpUdpSocket.write(buffer, 32); _dhcpUdpSocket.write(buffer, 32);
} }
// OPT - Magic Cookie // OPT - Magic Cookie
buffer[0] = (uint8_t)((MAGIC_COOKIE >> 24)& 0xFF); buffer[0] = (uint8_t)((MAGIC_COOKIE >> 24)& 0xFF);
buffer[1] = (uint8_t)((MAGIC_COOKIE >> 16)& 0xFF); buffer[1] = (uint8_t)((MAGIC_COOKIE >> 16)& 0xFF);
buffer[2] = (uint8_t)((MAGIC_COOKIE >> 8)& 0xFF); buffer[2] = (uint8_t)((MAGIC_COOKIE >> 8)& 0xFF);
buffer[3] = (uint8_t)(MAGIC_COOKIE& 0xFF); buffer[3] = (uint8_t)(MAGIC_COOKIE& 0xFF);
// OPT - message type // OPT - message type
buffer[4] = dhcpMessageType; buffer[4] = dhcpMessageType;
buffer[5] = 0x01; buffer[5] = 0x01;
buffer[6] = messageType; //DHCP_REQUEST; buffer[6] = messageType; //DHCP_REQUEST;
// OPT - client identifier // OPT - client identifier
buffer[7] = dhcpClientIdentifier; buffer[7] = dhcpClientIdentifier;
buffer[8] = 0x07; buffer[8] = 0x07;
buffer[9] = 0x01; buffer[9] = 0x01;
memcpy(buffer + 10, _dhcpMacAddr, 6); memcpy(buffer + 10, _dhcpMacAddr, 6);
// OPT - host name // OPT - host name
buffer[16] = hostName; buffer[16] = hostName;
buffer[17] = strlen(HOST_NAME) + 6; // length of hostname + last 3 bytes of mac address buffer[17] = strlen(HOST_NAME) + 6; // length of hostname + last 3 bytes of mac address
strcpy((char*)&(buffer[18]), HOST_NAME); strcpy((char*)&(buffer[18]), HOST_NAME);
printByte((char*)&(buffer[24]), _dhcpMacAddr[3]); printByte((char*)&(buffer[24]), _dhcpMacAddr[3]);
printByte((char*)&(buffer[26]), _dhcpMacAddr[4]); printByte((char*)&(buffer[26]), _dhcpMacAddr[4]);
printByte((char*)&(buffer[28]), _dhcpMacAddr[5]); printByte((char*)&(buffer[28]), _dhcpMacAddr[5]);
//put data in W5100 transmit buffer //put data in W5100 transmit buffer
_dhcpUdpSocket.write(buffer, 30); _dhcpUdpSocket.write(buffer, 30);
if(messageType == DHCP_REQUEST) if(messageType == DHCP_REQUEST)
{ {
buffer[0] = dhcpRequestedIPaddr; buffer[0] = dhcpRequestedIPaddr;
buffer[1] = 0x04; buffer[1] = 0x04;
buffer[2] = _dhcpLocalIp[0]; buffer[2] = _dhcpLocalIp[0];
buffer[3] = _dhcpLocalIp[1]; buffer[3] = _dhcpLocalIp[1];
buffer[4] = _dhcpLocalIp[2]; buffer[4] = _dhcpLocalIp[2];
buffer[5] = _dhcpLocalIp[3]; buffer[5] = _dhcpLocalIp[3];
buffer[6] = dhcpServerIdentifier; buffer[6] = dhcpServerIdentifier;
buffer[7] = 0x04; buffer[7] = 0x04;
buffer[8] = _dhcpDhcpServerIp[0]; buffer[8] = _dhcpDhcpServerIp[0];
buffer[9] = _dhcpDhcpServerIp[1]; buffer[9] = _dhcpDhcpServerIp[1];
buffer[10] = _dhcpDhcpServerIp[2]; buffer[10] = _dhcpDhcpServerIp[2];
buffer[11] = _dhcpDhcpServerIp[3]; buffer[11] = _dhcpDhcpServerIp[3];
//put data in W5100 transmit buffer //put data in W5100 transmit buffer
_dhcpUdpSocket.write(buffer, 12); _dhcpUdpSocket.write(buffer, 12);
} }
buffer[0] = dhcpParamRequest; buffer[0] = dhcpParamRequest;
buffer[1] = 0x06; buffer[1] = 0x06;
buffer[2] = subnetMask; buffer[2] = subnetMask;
buffer[3] = routersOnSubnet; buffer[3] = routersOnSubnet;
buffer[4] = dns; buffer[4] = dns;
buffer[5] = domainName; buffer[5] = domainName;
buffer[6] = dhcpT1value; buffer[6] = dhcpT1value;
buffer[7] = dhcpT2value; buffer[7] = dhcpT2value;
buffer[8] = endOption; buffer[8] = endOption;
//put data in W5100 transmit buffer //put data in W5100 transmit buffer
_dhcpUdpSocket.write(buffer, 9); _dhcpUdpSocket.write(buffer, 9);
_dhcpUdpSocket.endPacket(); _dhcpUdpSocket.endPacket();
} }
uint8_t DhcpClass::parseDHCPResponse(unsigned long responseTimeout, uint32_t& transactionId) uint8_t DhcpClass::parseDHCPResponse(unsigned long responseTimeout, uint32_t& transactionId)
{ {
uint8_t type = 0; uint8_t type = 0;
uint8_t opt_len = 0; uint8_t opt_len = 0;
unsigned long startTime = millis(); unsigned long startTime = millis();
while(_dhcpUdpSocket.parsePacket() <= 0) while(_dhcpUdpSocket.parsePacket() <= 0)
{ {
if((millis() - startTime) > responseTimeout) if((millis() - startTime) > responseTimeout)
{ {
return 255; return 255;
} }
delay(50); delay(50);
} }
// start reading in the packet // start reading in the packet
RIP_MSG_FIXED fixedMsg; RIP_MSG_FIXED fixedMsg;
_dhcpUdpSocket.read((uint8_t*)&fixedMsg, sizeof(RIP_MSG_FIXED)); _dhcpUdpSocket.read((uint8_t*)&fixedMsg, sizeof(RIP_MSG_FIXED));
if(fixedMsg.op == DHCP_BOOTREPLY && _dhcpUdpSocket.remotePort() == DHCP_SERVER_PORT) if(fixedMsg.op == DHCP_BOOTREPLY && _dhcpUdpSocket.remotePort() == DHCP_SERVER_PORT)
{ {
transactionId = ntohl(fixedMsg.xid); transactionId = ntohl(fixedMsg.xid);
if(memcmp(fixedMsg.chaddr, _dhcpMacAddr, 6) != 0 || (transactionId < _dhcpInitialTransactionId) || (transactionId > _dhcpTransactionId)) if(memcmp(fixedMsg.chaddr, _dhcpMacAddr, 6) != 0 || (transactionId < _dhcpInitialTransactionId) || (transactionId > _dhcpTransactionId))
{ {
// Need to read the rest of the packet here regardless // Need to read the rest of the packet here regardless
_dhcpUdpSocket.flush(); _dhcpUdpSocket.flush();
return 0; return 0;
} }
memcpy(_dhcpLocalIp, fixedMsg.yiaddr, 4); memcpy(_dhcpLocalIp, fixedMsg.yiaddr, 4);
// Skip to the option part // Skip to the option part
// Doing this a byte at a time so we don't have to put a big buffer // Doing this a byte at a time so we don't have to put a big buffer
// on the stack (as we don't have lots of memory lying around) // on the stack (as we don't have lots of memory lying around)
for (int i =0; i < (240 - (int)sizeof(RIP_MSG_FIXED)); i++) for (int i =0; i < (240 - (int)sizeof(RIP_MSG_FIXED)); i++)
{ {
_dhcpUdpSocket.read(); // we don't care about the returned byte _dhcpUdpSocket.read(); // we don't care about the returned byte
} }
while (_dhcpUdpSocket.available() > 0) while (_dhcpUdpSocket.available() > 0)
{ {
switch (_dhcpUdpSocket.read()) switch (_dhcpUdpSocket.read())
{ {
case endOption : case endOption :
break; break;
case padOption : case padOption :
break; break;
case dhcpMessageType : case dhcpMessageType :
opt_len = _dhcpUdpSocket.read(); opt_len = _dhcpUdpSocket.read();
type = _dhcpUdpSocket.read(); type = _dhcpUdpSocket.read();
break; break;
case subnetMask : case subnetMask :
opt_len = _dhcpUdpSocket.read(); opt_len = _dhcpUdpSocket.read();
_dhcpUdpSocket.read(_dhcpSubnetMask, 4); _dhcpUdpSocket.read(_dhcpSubnetMask, 4);
break; break;
case routersOnSubnet : case routersOnSubnet :
opt_len = _dhcpUdpSocket.read(); opt_len = _dhcpUdpSocket.read();
_dhcpUdpSocket.read(_dhcpGatewayIp, 4); _dhcpUdpSocket.read(_dhcpGatewayIp, 4);
for (int i = 0; i < opt_len-4; i++) for (int i = 0; i < opt_len-4; i++)
{ {
_dhcpUdpSocket.read(); _dhcpUdpSocket.read();
} }
break; break;
case dns : case dns :
opt_len = _dhcpUdpSocket.read(); opt_len = _dhcpUdpSocket.read();
_dhcpUdpSocket.read(_dhcpDnsServerIp, 4); _dhcpUdpSocket.read(_dhcpDnsServerIp, 4);
for (int i = 0; i < opt_len-4; i++) for (int i = 0; i < opt_len-4; i++)
{ {
_dhcpUdpSocket.read(); _dhcpUdpSocket.read();
} }
break; break;
case dhcpServerIdentifier : case dhcpServerIdentifier :
opt_len = _dhcpUdpSocket.read(); opt_len = _dhcpUdpSocket.read();
if( *((uint32_t*)_dhcpDhcpServerIp) == 0 || if( *((uint32_t*)_dhcpDhcpServerIp) == 0 ||
IPAddress(_dhcpDhcpServerIp) == _dhcpUdpSocket.remoteIP() ) IPAddress(_dhcpDhcpServerIp) == _dhcpUdpSocket.remoteIP() )
{ {
_dhcpUdpSocket.read(_dhcpDhcpServerIp, sizeof(_dhcpDhcpServerIp)); _dhcpUdpSocket.read(_dhcpDhcpServerIp, sizeof(_dhcpDhcpServerIp));
} }
else else
{ {
// Skip over the rest of this option // Skip over the rest of this option
while (opt_len--) while (opt_len--)
{ {
_dhcpUdpSocket.read(); _dhcpUdpSocket.read();
} }
} }
break; break;
case dhcpT1value : case dhcpT1value :
opt_len = _dhcpUdpSocket.read(); opt_len = _dhcpUdpSocket.read();
_dhcpUdpSocket.read((uint8_t*)&_dhcpT1, sizeof(_dhcpT1)); _dhcpUdpSocket.read((uint8_t*)&_dhcpT1, sizeof(_dhcpT1));
_dhcpT1 = ntohl(_dhcpT1); _dhcpT1 = ntohl(_dhcpT1);
break; break;
case dhcpT2value : case dhcpT2value :
opt_len = _dhcpUdpSocket.read(); opt_len = _dhcpUdpSocket.read();
_dhcpUdpSocket.read((uint8_t*)&_dhcpT2, sizeof(_dhcpT2)); _dhcpUdpSocket.read((uint8_t*)&_dhcpT2, sizeof(_dhcpT2));
_dhcpT2 = ntohl(_dhcpT2); _dhcpT2 = ntohl(_dhcpT2);
break; break;
case dhcpIPaddrLeaseTime : case dhcpIPaddrLeaseTime :
opt_len = _dhcpUdpSocket.read(); opt_len = _dhcpUdpSocket.read();
_dhcpUdpSocket.read((uint8_t*)&_dhcpLeaseTime, sizeof(_dhcpLeaseTime)); _dhcpUdpSocket.read((uint8_t*)&_dhcpLeaseTime, sizeof(_dhcpLeaseTime));
_dhcpLeaseTime = ntohl(_dhcpLeaseTime); _dhcpLeaseTime = ntohl(_dhcpLeaseTime);
_renewInSec = _dhcpLeaseTime; _renewInSec = _dhcpLeaseTime;
break; break;
default : default :
opt_len = _dhcpUdpSocket.read(); opt_len = _dhcpUdpSocket.read();
// Skip over the rest of this option // Skip over the rest of this option
while (opt_len--) while (opt_len--)
{ {
_dhcpUdpSocket.read(); _dhcpUdpSocket.read();
} }
break; break;
} }
} }
} }
// Need to skip to end of the packet regardless here // Need to skip to end of the packet regardless here
_dhcpUdpSocket.flush(); _dhcpUdpSocket.flush();
return type; return type;
} }
/* /*
returns: returns:
0/DHCP_CHECK_NONE: nothing happened 0/DHCP_CHECK_NONE: nothing happened
1/DHCP_CHECK_RENEW_FAIL: renew failed 1/DHCP_CHECK_RENEW_FAIL: renew failed
2/DHCP_CHECK_RENEW_OK: renew success 2/DHCP_CHECK_RENEW_OK: renew success
3/DHCP_CHECK_REBIND_FAIL: rebind fail 3/DHCP_CHECK_REBIND_FAIL: rebind fail
4/DHCP_CHECK_REBIND_OK: rebind success 4/DHCP_CHECK_REBIND_OK: rebind success
*/ */
int DhcpClass::checkLease(){ int DhcpClass::checkLease(){
//this uses a signed / unsigned trick to deal with millis overflow //this uses a signed / unsigned trick to deal with millis overflow
unsigned long now = millis(); unsigned long now = millis();
signed long snow = (long)now; signed long snow = (long)now;
int rc=DHCP_CHECK_NONE; int rc=DHCP_CHECK_NONE;
if (_lastCheck != 0){ if (_lastCheck != 0){
signed long factor; signed long factor;
//calc how many ms past the timeout we are //calc how many ms past the timeout we are
factor = snow - (long)_secTimeout; factor = snow - (long)_secTimeout;
//if on or passed the timeout, reduce the counters //if on or passed the timeout, reduce the counters
if ( factor >= 0 ){ if ( factor >= 0 ){
//next timeout should be now plus 1000 ms minus parts of second in factor //next timeout should be now plus 1000 ms minus parts of second in factor
_secTimeout = snow + 1000 - factor % 1000; _secTimeout = snow + 1000 - factor % 1000;
//how many seconds late are we, minimum 1 //how many seconds late are we, minimum 1
factor = factor / 1000 +1; factor = factor / 1000 +1;
//reduce the counters by that mouch //reduce the counters by that mouch
//if we can assume that the cycle time (factor) is fairly constant //if we can assume that the cycle time (factor) is fairly constant
//and if the remainder is less than cycle time * 2 //and if the remainder is less than cycle time * 2
//do it early instead of late //do it early instead of late
if(_renewInSec < factor*2 ) if(_renewInSec < factor*2 )
_renewInSec = 0; _renewInSec = 0;
else else
_renewInSec -= factor; _renewInSec -= factor;
if(_rebindInSec < factor*2 ) if(_rebindInSec < factor*2 )
_rebindInSec = 0; _rebindInSec = 0;
else else
_rebindInSec -= factor; _rebindInSec -= factor;
} }
//if we have a lease but should renew, do it //if we have a lease but should renew, do it
if (_dhcp_state == STATE_DHCP_LEASED && _renewInSec <=0){ if (_dhcp_state == STATE_DHCP_LEASED && _renewInSec <=0){
_dhcp_state = STATE_DHCP_REREQUEST; _dhcp_state = STATE_DHCP_REREQUEST;
rc = 1 + request_DHCP_lease(); rc = 1 + request_DHCP_lease();
} }
//if we have a lease or is renewing but should bind, do it //if we have a lease or is renewing but should bind, do it
if( (_dhcp_state == STATE_DHCP_LEASED || _dhcp_state == STATE_DHCP_START) && _rebindInSec <=0){ if( (_dhcp_state == STATE_DHCP_LEASED || _dhcp_state == STATE_DHCP_START) && _rebindInSec <=0){
//this should basically restart completely //this should basically restart completely
_dhcp_state = STATE_DHCP_START; _dhcp_state = STATE_DHCP_START;
reset_DHCP_lease(); reset_DHCP_lease();
rc = 3 + request_DHCP_lease(); rc = 3 + request_DHCP_lease();
} }
} }
else{ else{
_secTimeout = snow + 1000; _secTimeout = snow + 1000;
} }
_lastCheck = now; _lastCheck = now;
return rc; return rc;
} }
IPAddress DhcpClass::getLocalIp() IPAddress DhcpClass::getLocalIp()
{ {
return IPAddress(_dhcpLocalIp); return IPAddress(_dhcpLocalIp);
} }
IPAddress DhcpClass::getSubnetMask() IPAddress DhcpClass::getSubnetMask()
{ {
return IPAddress(_dhcpSubnetMask); return IPAddress(_dhcpSubnetMask);
} }
IPAddress DhcpClass::getGatewayIp() IPAddress DhcpClass::getGatewayIp()
{ {
return IPAddress(_dhcpGatewayIp); return IPAddress(_dhcpGatewayIp);
} }
IPAddress DhcpClass::getDhcpServerIp() IPAddress DhcpClass::getDhcpServerIp()
{ {
return IPAddress(_dhcpDhcpServerIp); return IPAddress(_dhcpDhcpServerIp);
} }
IPAddress DhcpClass::getDnsServerIp() IPAddress DhcpClass::getDnsServerIp()
{ {
return IPAddress(_dhcpDnsServerIp); return IPAddress(_dhcpDnsServerIp);
} }
void DhcpClass::printByte(char * buf, uint8_t n ) { void DhcpClass::printByte(char * buf, uint8_t n ) {
char *str = &buf[1]; char *str = &buf[1];
buf[0]='0'; buf[0]='0';
do { do {
unsigned long m = n; unsigned long m = n;
n /= 16; n /= 16;
char c = m - 16 * n; char c = m - 16 * n;
*str-- = c < 10 ? c + '0' : c + 'A' - 10; *str-- = c < 10 ? c + '0' : c + 'A' - 10;
} while(n); } while(n);
} }
+178 -178
View File
@@ -1,178 +1,178 @@
// DHCP Library v0.3 - April 25, 2009 // DHCP Library v0.3 - April 25, 2009
// Author: Jordan Terrell - blog.jordanterrell.com // Author: Jordan Terrell - blog.jordanterrell.com
#ifndef Dhcp_h #ifndef Dhcp_h
#define Dhcp_h #define Dhcp_h
#include "UIPUdp.h" #include "UIPUdp.h"
/* DHCP state machine. */ /* DHCP state machine. */
#define STATE_DHCP_START 0 #define STATE_DHCP_START 0
#define STATE_DHCP_DISCOVER 1 #define STATE_DHCP_DISCOVER 1
#define STATE_DHCP_REQUEST 2 #define STATE_DHCP_REQUEST 2
#define STATE_DHCP_LEASED 3 #define STATE_DHCP_LEASED 3
#define STATE_DHCP_REREQUEST 4 #define STATE_DHCP_REREQUEST 4
#define STATE_DHCP_RELEASE 5 #define STATE_DHCP_RELEASE 5
#define DHCP_FLAGSBROADCAST 0x8000 #define DHCP_FLAGSBROADCAST 0x8000
/* UDP port numbers for DHCP */ /* UDP port numbers for DHCP */
#define DHCP_SERVER_PORT 67 /* from server to client */ #define DHCP_SERVER_PORT 67 /* from server to client */
#define DHCP_CLIENT_PORT 68 /* from client to server */ #define DHCP_CLIENT_PORT 68 /* from client to server */
/* DHCP message OP code */ /* DHCP message OP code */
#define DHCP_BOOTREQUEST 1 #define DHCP_BOOTREQUEST 1
#define DHCP_BOOTREPLY 2 #define DHCP_BOOTREPLY 2
/* DHCP message type */ /* DHCP message type */
#define DHCP_DISCOVER 1 #define DHCP_DISCOVER 1
#define DHCP_OFFER 2 #define DHCP_OFFER 2
#define DHCP_REQUEST 3 #define DHCP_REQUEST 3
#define DHCP_DECLINE 4 #define DHCP_DECLINE 4
#define DHCP_ACK 5 #define DHCP_ACK 5
#define DHCP_NAK 6 #define DHCP_NAK 6
#define DHCP_RELEASE 7 #define DHCP_RELEASE 7
#define DHCP_INFORM 8 #define DHCP_INFORM 8
#define DHCP_HTYPE10MB 1 #define DHCP_HTYPE10MB 1
#define DHCP_HTYPE100MB 2 #define DHCP_HTYPE100MB 2
#define DHCP_HLENETHERNET 6 #define DHCP_HLENETHERNET 6
#define DHCP_HOPS 0 #define DHCP_HOPS 0
#define DHCP_SECS 0 #define DHCP_SECS 0
#define MAGIC_COOKIE 0x63825363 #define MAGIC_COOKIE 0x63825363
#define MAX_DHCP_OPT 16 #define MAX_DHCP_OPT 16
#define HOST_NAME "ENC28J" #define HOST_NAME "ENC28J"
#define DEFAULT_LEASE (900) //default lease time in seconds #define DEFAULT_LEASE (900) //default lease time in seconds
#define DHCP_CHECK_NONE (0) #define DHCP_CHECK_NONE (0)
#define DHCP_CHECK_RENEW_FAIL (1) #define DHCP_CHECK_RENEW_FAIL (1)
#define DHCP_CHECK_RENEW_OK (2) #define DHCP_CHECK_RENEW_OK (2)
#define DHCP_CHECK_REBIND_FAIL (3) #define DHCP_CHECK_REBIND_FAIL (3)
#define DHCP_CHECK_REBIND_OK (4) #define DHCP_CHECK_REBIND_OK (4)
enum enum
{ {
padOption = 0, padOption = 0,
subnetMask = 1, subnetMask = 1,
timerOffset = 2, timerOffset = 2,
routersOnSubnet = 3, routersOnSubnet = 3,
/* timeServer = 4, /* timeServer = 4,
nameServer = 5,*/ nameServer = 5,*/
dns = 6, dns = 6,
/*logServer = 7, /*logServer = 7,
cookieServer = 8, cookieServer = 8,
lprServer = 9, lprServer = 9,
impressServer = 10, impressServer = 10,
resourceLocationServer = 11,*/ resourceLocationServer = 11,*/
hostName = 12, hostName = 12,
/*bootFileSize = 13, /*bootFileSize = 13,
meritDumpFile = 14,*/ meritDumpFile = 14,*/
domainName = 15, domainName = 15,
/*swapServer = 16, /*swapServer = 16,
rootPath = 17, rootPath = 17,
extentionsPath = 18, extentionsPath = 18,
IPforwarding = 19, IPforwarding = 19,
nonLocalSourceRouting = 20, nonLocalSourceRouting = 20,
policyFilter = 21, policyFilter = 21,
maxDgramReasmSize = 22, maxDgramReasmSize = 22,
defaultIPTTL = 23, defaultIPTTL = 23,
pathMTUagingTimeout = 24, pathMTUagingTimeout = 24,
pathMTUplateauTable = 25, pathMTUplateauTable = 25,
ifMTU = 26, ifMTU = 26,
allSubnetsLocal = 27, allSubnetsLocal = 27,
broadcastAddr = 28, broadcastAddr = 28,
performMaskDiscovery = 29, performMaskDiscovery = 29,
maskSupplier = 30, maskSupplier = 30,
performRouterDiscovery = 31, performRouterDiscovery = 31,
routerSolicitationAddr = 32, routerSolicitationAddr = 32,
staticRoute = 33, staticRoute = 33,
trailerEncapsulation = 34, trailerEncapsulation = 34,
arpCacheTimeout = 35, arpCacheTimeout = 35,
ethernetEncapsulation = 36, ethernetEncapsulation = 36,
tcpDefaultTTL = 37, tcpDefaultTTL = 37,
tcpKeepaliveInterval = 38, tcpKeepaliveInterval = 38,
tcpKeepaliveGarbage = 39, tcpKeepaliveGarbage = 39,
nisDomainName = 40, nisDomainName = 40,
nisServers = 41, nisServers = 41,
ntpServers = 42, ntpServers = 42,
vendorSpecificInfo = 43, vendorSpecificInfo = 43,
netBIOSnameServer = 44, netBIOSnameServer = 44,
netBIOSdgramDistServer = 45, netBIOSdgramDistServer = 45,
netBIOSnodeType = 46, netBIOSnodeType = 46,
netBIOSscope = 47, netBIOSscope = 47,
xFontServer = 48, xFontServer = 48,
xDisplayManager = 49,*/ xDisplayManager = 49,*/
dhcpRequestedIPaddr = 50, dhcpRequestedIPaddr = 50,
dhcpIPaddrLeaseTime = 51, dhcpIPaddrLeaseTime = 51,
/*dhcpOptionOverload = 52,*/ /*dhcpOptionOverload = 52,*/
dhcpMessageType = 53, dhcpMessageType = 53,
dhcpServerIdentifier = 54, dhcpServerIdentifier = 54,
dhcpParamRequest = 55, dhcpParamRequest = 55,
/*dhcpMsg = 56, /*dhcpMsg = 56,
dhcpMaxMsgSize = 57,*/ dhcpMaxMsgSize = 57,*/
dhcpT1value = 58, dhcpT1value = 58,
dhcpT2value = 59, dhcpT2value = 59,
/*dhcpClassIdentifier = 60,*/ /*dhcpClassIdentifier = 60,*/
dhcpClientIdentifier = 61, dhcpClientIdentifier = 61,
endOption = 255 endOption = 255
}; };
typedef struct _RIP_MSG_FIXED typedef struct _RIP_MSG_FIXED
{ {
uint8_t op; uint8_t op;
uint8_t htype; uint8_t htype;
uint8_t hlen; uint8_t hlen;
uint8_t hops; uint8_t hops;
uint32_t xid; uint32_t xid;
uint16_t secs; uint16_t secs;
uint16_t flags; uint16_t flags;
uint8_t ciaddr[4]; uint8_t ciaddr[4];
uint8_t yiaddr[4]; uint8_t yiaddr[4];
uint8_t siaddr[4]; uint8_t siaddr[4];
uint8_t giaddr[4]; uint8_t giaddr[4];
uint8_t chaddr[6]; uint8_t chaddr[6];
}RIP_MSG_FIXED; }RIP_MSG_FIXED;
class DhcpClass { class DhcpClass {
private: private:
uint32_t _dhcpInitialTransactionId; uint32_t _dhcpInitialTransactionId;
uint32_t _dhcpTransactionId; uint32_t _dhcpTransactionId;
uint8_t _dhcpMacAddr[6]; uint8_t _dhcpMacAddr[6];
uint8_t _dhcpLocalIp[4]; uint8_t _dhcpLocalIp[4];
uint8_t _dhcpSubnetMask[4]; uint8_t _dhcpSubnetMask[4];
uint8_t _dhcpGatewayIp[4]; uint8_t _dhcpGatewayIp[4];
uint8_t _dhcpDhcpServerIp[4]; uint8_t _dhcpDhcpServerIp[4];
uint8_t _dhcpDnsServerIp[4]; uint8_t _dhcpDnsServerIp[4];
uint32_t _dhcpLeaseTime; uint32_t _dhcpLeaseTime;
uint32_t _dhcpT1, _dhcpT2; uint32_t _dhcpT1, _dhcpT2;
signed long _renewInSec; signed long _renewInSec;
signed long _rebindInSec; signed long _rebindInSec;
signed long _lastCheck; signed long _lastCheck;
unsigned long _timeout; unsigned long _timeout;
unsigned long _responseTimeout; unsigned long _responseTimeout;
unsigned long _secTimeout; unsigned long _secTimeout;
uint8_t _dhcp_state; uint8_t _dhcp_state;
UIPUDP _dhcpUdpSocket; UIPUDP _dhcpUdpSocket;
int request_DHCP_lease(); int request_DHCP_lease();
void reset_DHCP_lease(); void reset_DHCP_lease();
void presend_DHCP(); void presend_DHCP();
void send_DHCP_MESSAGE(uint8_t, uint16_t); void send_DHCP_MESSAGE(uint8_t, uint16_t);
void printByte(char *, uint8_t); void printByte(char *, uint8_t);
uint8_t parseDHCPResponse(unsigned long responseTimeout, uint32_t& transactionId); uint8_t parseDHCPResponse(unsigned long responseTimeout, uint32_t& transactionId);
public: public:
IPAddress getLocalIp(); IPAddress getLocalIp();
IPAddress getSubnetMask(); IPAddress getSubnetMask();
IPAddress getGatewayIp(); IPAddress getGatewayIp();
IPAddress getDhcpServerIp(); IPAddress getDhcpServerIp();
IPAddress getDnsServerIp(); IPAddress getDnsServerIp();
int beginWithDHCP(uint8_t *, unsigned long timeout = 60000, unsigned long responseTimeout = 4000); int beginWithDHCP(uint8_t *, unsigned long timeout = 60000, unsigned long responseTimeout = 4000);
int checkLease(); int checkLease();
}; };
#endif #endif
+41 -41
View File
@@ -1,41 +1,41 @@
// Arduino DNS client for Enc28J60-based Ethernet shield // Arduino DNS client for Enc28J60-based Ethernet shield
// (c) Copyright 2009-2010 MCQN Ltd. // (c) Copyright 2009-2010 MCQN Ltd.
// Released under Apache License, version 2.0 // Released under Apache License, version 2.0
#ifndef DNSClient_h #ifndef DNSClient_h
#define DNSClient_h #define DNSClient_h
#include <UIPUdp.h> #include <UIPUdp.h>
class DNSClient class DNSClient
{ {
public: public:
// ctor // ctor
void begin(const IPAddress& aDNSServer); void begin(const IPAddress& aDNSServer);
/** Convert a numeric IP address string into a four-byte IP address. /** Convert a numeric IP address string into a four-byte IP address.
@param aIPAddrString IP address to convert @param aIPAddrString IP address to convert
@param aResult IPAddress structure to store the returned IP address @param aResult IPAddress structure to store the returned IP address
@result 1 if aIPAddrString was successfully converted to an IP address, @result 1 if aIPAddrString was successfully converted to an IP address,
else error code else error code
*/ */
int inet_aton(const char *aIPAddrString, IPAddress& aResult); int inet_aton(const char *aIPAddrString, IPAddress& aResult);
/** Resolve the given hostname to an IP address. /** Resolve the given hostname to an IP address.
@param aHostname Name to be resolved @param aHostname Name to be resolved
@param aResult IPAddress structure to store the returned IP address @param aResult IPAddress structure to store the returned IP address
@result 1 if aIPAddrString was successfully converted to an IP address, @result 1 if aIPAddrString was successfully converted to an IP address,
else error code else error code
*/ */
int getHostByName(const char* aHostname, IPAddress& aResult); int getHostByName(const char* aHostname, IPAddress& aResult);
protected: protected:
uint16_t BuildRequest(const char* aName); uint16_t BuildRequest(const char* aName);
uint16_t ProcessResponse(uint16_t aTimeout, IPAddress& aAddress); uint16_t ProcessResponse(uint16_t aTimeout, IPAddress& aAddress);
IPAddress iDNSServer; IPAddress iDNSServer;
uint16_t iRequestId; uint16_t iRequestId;
UIPUDP iUdp; UIPUDP iUdp;
}; };
#endif #endif
+478 -478
View File
@@ -1,478 +1,478 @@
// DHCP Library v0.3 - April 25, 2009 // DHCP Library v0.3 - April 25, 2009
// Author: Jordan Terrell - blog.jordanterrell.com // Author: Jordan Terrell - blog.jordanterrell.com
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include "Dhcp.h" #include "Dhcp.h"
#include "Arduino.h" #include "Arduino.h"
#include "utility/util.h" #include "utility/util.h"
int DhcpClass::beginWithDHCP(uint8_t *mac, unsigned long timeout, unsigned long responseTimeout) int DhcpClass::beginWithDHCP(uint8_t *mac, unsigned long timeout, unsigned long responseTimeout)
{ {
_dhcpLeaseTime=0; _dhcpLeaseTime=0;
_dhcpT1=0; _dhcpT1=0;
_dhcpT2=0; _dhcpT2=0;
_lastCheck=0; _lastCheck=0;
_timeout = timeout; _timeout = timeout;
_responseTimeout = responseTimeout; _responseTimeout = responseTimeout;
// zero out _dhcpMacAddr // zero out _dhcpMacAddr
memset(_dhcpMacAddr, 0, 6); memset(_dhcpMacAddr, 0, 6);
reset_DHCP_lease(); reset_DHCP_lease();
memcpy((void*)_dhcpMacAddr, (void*)mac, 6); memcpy((void*)_dhcpMacAddr, (void*)mac, 6);
_dhcp_state = STATE_DHCP_START; _dhcp_state = STATE_DHCP_START;
return request_DHCP_lease(); return request_DHCP_lease();
} }
void DhcpClass::reset_DHCP_lease(){ void DhcpClass::reset_DHCP_lease(){
// zero out _dhcpSubnetMask, _dhcpGatewayIp, _dhcpLocalIp, _dhcpDhcpServerIp, _dhcpDnsServerIp // zero out _dhcpSubnetMask, _dhcpGatewayIp, _dhcpLocalIp, _dhcpDhcpServerIp, _dhcpDnsServerIp
memset(_dhcpLocalIp, 0, 20); memset(_dhcpLocalIp, 0, 20);
} }
//return:0 on error, 1 if request is sent and response is received //return:0 on error, 1 if request is sent and response is received
int DhcpClass::request_DHCP_lease(){ int DhcpClass::request_DHCP_lease(){
uint8_t messageType = 0; uint8_t messageType = 0;
// Pick an initial transaction ID // Pick an initial transaction ID
_dhcpTransactionId = random(1UL, 2000UL); _dhcpTransactionId = random(1UL, 2000UL);
_dhcpInitialTransactionId = _dhcpTransactionId; _dhcpInitialTransactionId = _dhcpTransactionId;
_dhcpUdpSocket.stop(); _dhcpUdpSocket.stop();
if (_dhcpUdpSocket.begin(DHCP_CLIENT_PORT) == 0) if (_dhcpUdpSocket.begin(DHCP_CLIENT_PORT) == 0)
{ {
// Couldn't get a socket // Couldn't get a socket
return 0; return 0;
} }
presend_DHCP(); presend_DHCP();
int result = 0; int result = 0;
unsigned long startTime = millis(); unsigned long startTime = millis();
while(_dhcp_state != STATE_DHCP_LEASED) while(_dhcp_state != STATE_DHCP_LEASED)
{ {
if(_dhcp_state == STATE_DHCP_START) if(_dhcp_state == STATE_DHCP_START)
{ {
_dhcpTransactionId++; _dhcpTransactionId++;
send_DHCP_MESSAGE(DHCP_DISCOVER, ((millis() - startTime) / 1000)); send_DHCP_MESSAGE(DHCP_DISCOVER, ((millis() - startTime) / 1000));
_dhcp_state = STATE_DHCP_DISCOVER; _dhcp_state = STATE_DHCP_DISCOVER;
} }
else if(_dhcp_state == STATE_DHCP_REREQUEST){ else if(_dhcp_state == STATE_DHCP_REREQUEST){
_dhcpTransactionId++; _dhcpTransactionId++;
send_DHCP_MESSAGE(DHCP_REQUEST, ((millis() - startTime)/1000)); send_DHCP_MESSAGE(DHCP_REQUEST, ((millis() - startTime)/1000));
_dhcp_state = STATE_DHCP_REQUEST; _dhcp_state = STATE_DHCP_REQUEST;
} }
else if(_dhcp_state == STATE_DHCP_DISCOVER) else if(_dhcp_state == STATE_DHCP_DISCOVER)
{ {
uint32_t respId; uint32_t respId;
messageType = parseDHCPResponse(_responseTimeout, respId); messageType = parseDHCPResponse(_responseTimeout, respId);
if(messageType == DHCP_OFFER) if(messageType == DHCP_OFFER)
{ {
// We'll use the transaction ID that the offer came with, // We'll use the transaction ID that the offer came with,
// rather than the one we were up to // rather than the one we were up to
_dhcpTransactionId = respId; _dhcpTransactionId = respId;
send_DHCP_MESSAGE(DHCP_REQUEST, ((millis() - startTime) / 1000)); send_DHCP_MESSAGE(DHCP_REQUEST, ((millis() - startTime) / 1000));
_dhcp_state = STATE_DHCP_REQUEST; _dhcp_state = STATE_DHCP_REQUEST;
} }
} }
else if(_dhcp_state == STATE_DHCP_REQUEST) else if(_dhcp_state == STATE_DHCP_REQUEST)
{ {
uint32_t respId; uint32_t respId;
messageType = parseDHCPResponse(_responseTimeout, respId); messageType = parseDHCPResponse(_responseTimeout, respId);
if(messageType == DHCP_ACK) if(messageType == DHCP_ACK)
{ {
_dhcp_state = STATE_DHCP_LEASED; _dhcp_state = STATE_DHCP_LEASED;
result = 1; result = 1;
//use default lease time if we didn't get it //use default lease time if we didn't get it
if(_dhcpLeaseTime == 0){ if(_dhcpLeaseTime == 0){
_dhcpLeaseTime = DEFAULT_LEASE; _dhcpLeaseTime = DEFAULT_LEASE;
} }
//calculate T1 & T2 if we didn't get it //calculate T1 & T2 if we didn't get it
if(_dhcpT1 == 0){ if(_dhcpT1 == 0){
//T1 should be 50% of _dhcpLeaseTime //T1 should be 50% of _dhcpLeaseTime
_dhcpT1 = _dhcpLeaseTime >> 1; _dhcpT1 = _dhcpLeaseTime >> 1;
} }
if(_dhcpT2 == 0){ if(_dhcpT2 == 0){
//T2 should be 87.5% (7/8ths) of _dhcpLeaseTime //T2 should be 87.5% (7/8ths) of _dhcpLeaseTime
_dhcpT2 = _dhcpT1 << 1; _dhcpT2 = _dhcpT1 << 1;
} }
_renewInSec = _dhcpT1; _renewInSec = _dhcpT1;
_rebindInSec = _dhcpT2; _rebindInSec = _dhcpT2;
} }
else if(messageType == DHCP_NAK) else if(messageType == DHCP_NAK)
_dhcp_state = STATE_DHCP_START; _dhcp_state = STATE_DHCP_START;
} }
if(messageType == 255) if(messageType == 255)
{ {
messageType = 0; messageType = 0;
_dhcp_state = STATE_DHCP_START; _dhcp_state = STATE_DHCP_START;
} }
if(result != 1 && ((millis() - startTime) > _timeout)) if(result != 1 && ((millis() - startTime) > _timeout))
break; break;
} }
// We're done with the socket now // We're done with the socket now
_dhcpUdpSocket.stop(); _dhcpUdpSocket.stop();
_dhcpTransactionId++; _dhcpTransactionId++;
return result; return result;
} }
void DhcpClass::presend_DHCP() void DhcpClass::presend_DHCP()
{ {
} }
void DhcpClass::send_DHCP_MESSAGE(uint8_t messageType, uint16_t secondsElapsed) void DhcpClass::send_DHCP_MESSAGE(uint8_t messageType, uint16_t secondsElapsed)
{ {
uint8_t buffer[32]; uint8_t buffer[32];
memset(buffer, 0, 32); memset(buffer, 0, 32);
IPAddress dest_addr( 255, 255, 255, 255 ); // Broadcast address IPAddress dest_addr( 255, 255, 255, 255 ); // Broadcast address
if (-1 == _dhcpUdpSocket.beginPacket(dest_addr, DHCP_SERVER_PORT)) if (-1 == _dhcpUdpSocket.beginPacket(dest_addr, DHCP_SERVER_PORT))
{ {
// FIXME Need to return errors // FIXME Need to return errors
return; return;
} }
buffer[0] = DHCP_BOOTREQUEST; // op buffer[0] = DHCP_BOOTREQUEST; // op
buffer[1] = DHCP_HTYPE10MB; // htype buffer[1] = DHCP_HTYPE10MB; // htype
buffer[2] = DHCP_HLENETHERNET; // hlen buffer[2] = DHCP_HLENETHERNET; // hlen
buffer[3] = DHCP_HOPS; // hops buffer[3] = DHCP_HOPS; // hops
// xid // xid
unsigned long xid = htonl(_dhcpTransactionId); unsigned long xid = htonl(_dhcpTransactionId);
memcpy(buffer + 4, &(xid), 4); memcpy(buffer + 4, &(xid), 4);
// 8, 9 - seconds elapsed // 8, 9 - seconds elapsed
buffer[8] = ((secondsElapsed & 0xff00) >> 8); buffer[8] = ((secondsElapsed & 0xff00) >> 8);
buffer[9] = (secondsElapsed & 0x00ff); buffer[9] = (secondsElapsed & 0x00ff);
// flags // flags
unsigned short flags = htons(DHCP_FLAGSBROADCAST); unsigned short flags = htons(DHCP_FLAGSBROADCAST);
memcpy(buffer + 10, &(flags), 2); memcpy(buffer + 10, &(flags), 2);
// ciaddr: already zeroed // ciaddr: already zeroed
// yiaddr: already zeroed // yiaddr: already zeroed
// siaddr: already zeroed // siaddr: already zeroed
// giaddr: already zeroed // giaddr: already zeroed
//put data in W5100 transmit buffer //put data in W5100 transmit buffer
_dhcpUdpSocket.write(buffer, 28); _dhcpUdpSocket.write(buffer, 28);
memset(buffer, 0, 32); // clear local buffer memset(buffer, 0, 32); // clear local buffer
memcpy(buffer, _dhcpMacAddr, 6); // chaddr memcpy(buffer, _dhcpMacAddr, 6); // chaddr
//put data in W5100 transmit buffer //put data in W5100 transmit buffer
_dhcpUdpSocket.write(buffer, 16); _dhcpUdpSocket.write(buffer, 16);
memset(buffer, 0, 32); // clear local buffer memset(buffer, 0, 32); // clear local buffer
// leave zeroed out for sname && file // leave zeroed out for sname && file
// put in W5100 transmit buffer x 6 (192 bytes) // put in W5100 transmit buffer x 6 (192 bytes)
for(int i = 0; i < 6; i++) { for(int i = 0; i < 6; i++) {
_dhcpUdpSocket.write(buffer, 32); _dhcpUdpSocket.write(buffer, 32);
} }
// OPT - Magic Cookie // OPT - Magic Cookie
buffer[0] = (uint8_t)((MAGIC_COOKIE >> 24)& 0xFF); buffer[0] = (uint8_t)((MAGIC_COOKIE >> 24)& 0xFF);
buffer[1] = (uint8_t)((MAGIC_COOKIE >> 16)& 0xFF); buffer[1] = (uint8_t)((MAGIC_COOKIE >> 16)& 0xFF);
buffer[2] = (uint8_t)((MAGIC_COOKIE >> 8)& 0xFF); buffer[2] = (uint8_t)((MAGIC_COOKIE >> 8)& 0xFF);
buffer[3] = (uint8_t)(MAGIC_COOKIE& 0xFF); buffer[3] = (uint8_t)(MAGIC_COOKIE& 0xFF);
// OPT - message type // OPT - message type
buffer[4] = dhcpMessageType; buffer[4] = dhcpMessageType;
buffer[5] = 0x01; buffer[5] = 0x01;
buffer[6] = messageType; //DHCP_REQUEST; buffer[6] = messageType; //DHCP_REQUEST;
// OPT - client identifier // OPT - client identifier
buffer[7] = dhcpClientIdentifier; buffer[7] = dhcpClientIdentifier;
buffer[8] = 0x07; buffer[8] = 0x07;
buffer[9] = 0x01; buffer[9] = 0x01;
memcpy(buffer + 10, _dhcpMacAddr, 6); memcpy(buffer + 10, _dhcpMacAddr, 6);
// OPT - host name // OPT - host name
buffer[16] = hostName; buffer[16] = hostName;
buffer[17] = strlen(HOST_NAME) + 6; // length of hostname + last 3 bytes of mac address buffer[17] = strlen(HOST_NAME) + 6; // length of hostname + last 3 bytes of mac address
strcpy((char*)&(buffer[18]), HOST_NAME); strcpy((char*)&(buffer[18]), HOST_NAME);
printByte((char*)&(buffer[24]), _dhcpMacAddr[3]); printByte((char*)&(buffer[24]), _dhcpMacAddr[3]);
printByte((char*)&(buffer[26]), _dhcpMacAddr[4]); printByte((char*)&(buffer[26]), _dhcpMacAddr[4]);
printByte((char*)&(buffer[28]), _dhcpMacAddr[5]); printByte((char*)&(buffer[28]), _dhcpMacAddr[5]);
//put data in W5100 transmit buffer //put data in W5100 transmit buffer
_dhcpUdpSocket.write(buffer, 30); _dhcpUdpSocket.write(buffer, 30);
if(messageType == DHCP_REQUEST) if(messageType == DHCP_REQUEST)
{ {
buffer[0] = dhcpRequestedIPaddr; buffer[0] = dhcpRequestedIPaddr;
buffer[1] = 0x04; buffer[1] = 0x04;
buffer[2] = _dhcpLocalIp[0]; buffer[2] = _dhcpLocalIp[0];
buffer[3] = _dhcpLocalIp[1]; buffer[3] = _dhcpLocalIp[1];
buffer[4] = _dhcpLocalIp[2]; buffer[4] = _dhcpLocalIp[2];
buffer[5] = _dhcpLocalIp[3]; buffer[5] = _dhcpLocalIp[3];
buffer[6] = dhcpServerIdentifier; buffer[6] = dhcpServerIdentifier;
buffer[7] = 0x04; buffer[7] = 0x04;
buffer[8] = _dhcpDhcpServerIp[0]; buffer[8] = _dhcpDhcpServerIp[0];
buffer[9] = _dhcpDhcpServerIp[1]; buffer[9] = _dhcpDhcpServerIp[1];
buffer[10] = _dhcpDhcpServerIp[2]; buffer[10] = _dhcpDhcpServerIp[2];
buffer[11] = _dhcpDhcpServerIp[3]; buffer[11] = _dhcpDhcpServerIp[3];
//put data in W5100 transmit buffer //put data in W5100 transmit buffer
_dhcpUdpSocket.write(buffer, 12); _dhcpUdpSocket.write(buffer, 12);
} }
buffer[0] = dhcpParamRequest; buffer[0] = dhcpParamRequest;
buffer[1] = 0x06; buffer[1] = 0x06;
buffer[2] = subnetMask; buffer[2] = subnetMask;
buffer[3] = routersOnSubnet; buffer[3] = routersOnSubnet;
buffer[4] = dns; buffer[4] = dns;
buffer[5] = domainName; buffer[5] = domainName;
buffer[6] = dhcpT1value; buffer[6] = dhcpT1value;
buffer[7] = dhcpT2value; buffer[7] = dhcpT2value;
buffer[8] = endOption; buffer[8] = endOption;
//put data in W5100 transmit buffer //put data in W5100 transmit buffer
_dhcpUdpSocket.write(buffer, 9); _dhcpUdpSocket.write(buffer, 9);
_dhcpUdpSocket.endPacket(); _dhcpUdpSocket.endPacket();
} }
uint8_t DhcpClass::parseDHCPResponse(unsigned long responseTimeout, uint32_t& transactionId) uint8_t DhcpClass::parseDHCPResponse(unsigned long responseTimeout, uint32_t& transactionId)
{ {
uint8_t type = 0; uint8_t type = 0;
uint8_t opt_len = 0; uint8_t opt_len = 0;
unsigned long startTime = millis(); unsigned long startTime = millis();
while(_dhcpUdpSocket.parsePacket() <= 0) while(_dhcpUdpSocket.parsePacket() <= 0)
{ {
if((millis() - startTime) > responseTimeout) if((millis() - startTime) > responseTimeout)
{ {
return 255; return 255;
} }
delay(50); delay(50);
} }
// start reading in the packet // start reading in the packet
RIP_MSG_FIXED fixedMsg; RIP_MSG_FIXED fixedMsg;
_dhcpUdpSocket.read((uint8_t*)&fixedMsg, sizeof(RIP_MSG_FIXED)); _dhcpUdpSocket.read((uint8_t*)&fixedMsg, sizeof(RIP_MSG_FIXED));
if(fixedMsg.op == DHCP_BOOTREPLY && _dhcpUdpSocket.remotePort() == DHCP_SERVER_PORT) if(fixedMsg.op == DHCP_BOOTREPLY && _dhcpUdpSocket.remotePort() == DHCP_SERVER_PORT)
{ {
transactionId = ntohl(fixedMsg.xid); transactionId = ntohl(fixedMsg.xid);
if(memcmp(fixedMsg.chaddr, _dhcpMacAddr, 6) != 0 || (transactionId < _dhcpInitialTransactionId) || (transactionId > _dhcpTransactionId)) if(memcmp(fixedMsg.chaddr, _dhcpMacAddr, 6) != 0 || (transactionId < _dhcpInitialTransactionId) || (transactionId > _dhcpTransactionId))
{ {
// Need to read the rest of the packet here regardless // Need to read the rest of the packet here regardless
_dhcpUdpSocket.flush(); _dhcpUdpSocket.flush();
return 0; return 0;
} }
memcpy(_dhcpLocalIp, fixedMsg.yiaddr, 4); memcpy(_dhcpLocalIp, fixedMsg.yiaddr, 4);
// Skip to the option part // Skip to the option part
// Doing this a byte at a time so we don't have to put a big buffer // Doing this a byte at a time so we don't have to put a big buffer
// on the stack (as we don't have lots of memory lying around) // on the stack (as we don't have lots of memory lying around)
for (int i =0; i < (240 - (int)sizeof(RIP_MSG_FIXED)); i++) for (int i =0; i < (240 - (int)sizeof(RIP_MSG_FIXED)); i++)
{ {
_dhcpUdpSocket.read(); // we don't care about the returned byte _dhcpUdpSocket.read(); // we don't care about the returned byte
} }
while (_dhcpUdpSocket.available() > 0) while (_dhcpUdpSocket.available() > 0)
{ {
switch (_dhcpUdpSocket.read()) switch (_dhcpUdpSocket.read())
{ {
case endOption : case endOption :
break; break;
case padOption : case padOption :
break; break;
case dhcpMessageType : case dhcpMessageType :
opt_len = _dhcpUdpSocket.read(); opt_len = _dhcpUdpSocket.read();
type = _dhcpUdpSocket.read(); type = _dhcpUdpSocket.read();
break; break;
case subnetMask : case subnetMask :
opt_len = _dhcpUdpSocket.read(); opt_len = _dhcpUdpSocket.read();
_dhcpUdpSocket.read(_dhcpSubnetMask, 4); _dhcpUdpSocket.read(_dhcpSubnetMask, 4);
break; break;
case routersOnSubnet : case routersOnSubnet :
opt_len = _dhcpUdpSocket.read(); opt_len = _dhcpUdpSocket.read();
_dhcpUdpSocket.read(_dhcpGatewayIp, 4); _dhcpUdpSocket.read(_dhcpGatewayIp, 4);
for (int i = 0; i < opt_len-4; i++) for (int i = 0; i < opt_len-4; i++)
{ {
_dhcpUdpSocket.read(); _dhcpUdpSocket.read();
} }
break; break;
case dns : case dns :
opt_len = _dhcpUdpSocket.read(); opt_len = _dhcpUdpSocket.read();
_dhcpUdpSocket.read(_dhcpDnsServerIp, 4); _dhcpUdpSocket.read(_dhcpDnsServerIp, 4);
for (int i = 0; i < opt_len-4; i++) for (int i = 0; i < opt_len-4; i++)
{ {
_dhcpUdpSocket.read(); _dhcpUdpSocket.read();
} }
break; break;
case dhcpServerIdentifier : case dhcpServerIdentifier :
opt_len = _dhcpUdpSocket.read(); opt_len = _dhcpUdpSocket.read();
if( *((uint32_t*)_dhcpDhcpServerIp) == 0 || if( *((uint32_t*)_dhcpDhcpServerIp) == 0 ||
IPAddress(_dhcpDhcpServerIp) == _dhcpUdpSocket.remoteIP() ) IPAddress(_dhcpDhcpServerIp) == _dhcpUdpSocket.remoteIP() )
{ {
_dhcpUdpSocket.read(_dhcpDhcpServerIp, sizeof(_dhcpDhcpServerIp)); _dhcpUdpSocket.read(_dhcpDhcpServerIp, sizeof(_dhcpDhcpServerIp));
} }
else else
{ {
// Skip over the rest of this option // Skip over the rest of this option
while (opt_len--) while (opt_len--)
{ {
_dhcpUdpSocket.read(); _dhcpUdpSocket.read();
} }
} }
break; break;
case dhcpT1value : case dhcpT1value :
opt_len = _dhcpUdpSocket.read(); opt_len = _dhcpUdpSocket.read();
_dhcpUdpSocket.read((uint8_t*)&_dhcpT1, sizeof(_dhcpT1)); _dhcpUdpSocket.read((uint8_t*)&_dhcpT1, sizeof(_dhcpT1));
_dhcpT1 = ntohl(_dhcpT1); _dhcpT1 = ntohl(_dhcpT1);
break; break;
case dhcpT2value : case dhcpT2value :
opt_len = _dhcpUdpSocket.read(); opt_len = _dhcpUdpSocket.read();
_dhcpUdpSocket.read((uint8_t*)&_dhcpT2, sizeof(_dhcpT2)); _dhcpUdpSocket.read((uint8_t*)&_dhcpT2, sizeof(_dhcpT2));
_dhcpT2 = ntohl(_dhcpT2); _dhcpT2 = ntohl(_dhcpT2);
break; break;
case dhcpIPaddrLeaseTime : case dhcpIPaddrLeaseTime :
opt_len = _dhcpUdpSocket.read(); opt_len = _dhcpUdpSocket.read();
_dhcpUdpSocket.read((uint8_t*)&_dhcpLeaseTime, sizeof(_dhcpLeaseTime)); _dhcpUdpSocket.read((uint8_t*)&_dhcpLeaseTime, sizeof(_dhcpLeaseTime));
_dhcpLeaseTime = ntohl(_dhcpLeaseTime); _dhcpLeaseTime = ntohl(_dhcpLeaseTime);
_renewInSec = _dhcpLeaseTime; _renewInSec = _dhcpLeaseTime;
break; break;
default : default :
opt_len = _dhcpUdpSocket.read(); opt_len = _dhcpUdpSocket.read();
// Skip over the rest of this option // Skip over the rest of this option
while (opt_len--) while (opt_len--)
{ {
_dhcpUdpSocket.read(); _dhcpUdpSocket.read();
} }
break; break;
} }
} }
} }
// Need to skip to end of the packet regardless here // Need to skip to end of the packet regardless here
_dhcpUdpSocket.flush(); _dhcpUdpSocket.flush();
return type; return type;
} }
/* /*
returns: returns:
0/DHCP_CHECK_NONE: nothing happened 0/DHCP_CHECK_NONE: nothing happened
1/DHCP_CHECK_RENEW_FAIL: renew failed 1/DHCP_CHECK_RENEW_FAIL: renew failed
2/DHCP_CHECK_RENEW_OK: renew success 2/DHCP_CHECK_RENEW_OK: renew success
3/DHCP_CHECK_REBIND_FAIL: rebind fail 3/DHCP_CHECK_REBIND_FAIL: rebind fail
4/DHCP_CHECK_REBIND_OK: rebind success 4/DHCP_CHECK_REBIND_OK: rebind success
*/ */
int DhcpClass::checkLease(){ int DhcpClass::checkLease(){
//this uses a signed / unsigned trick to deal with millis overflow //this uses a signed / unsigned trick to deal with millis overflow
unsigned long now = millis(); unsigned long now = millis();
signed long snow = (long)now; signed long snow = (long)now;
int rc=DHCP_CHECK_NONE; int rc=DHCP_CHECK_NONE;
if (_lastCheck != 0){ if (_lastCheck != 0){
signed long factor; signed long factor;
//calc how many ms past the timeout we are //calc how many ms past the timeout we are
factor = snow - (long)_secTimeout; factor = snow - (long)_secTimeout;
//if on or passed the timeout, reduce the counters //if on or passed the timeout, reduce the counters
if ( factor >= 0 ){ if ( factor >= 0 ){
//next timeout should be now plus 1000 ms minus parts of second in factor //next timeout should be now plus 1000 ms minus parts of second in factor
_secTimeout = snow + 1000 - factor % 1000; _secTimeout = snow + 1000 - factor % 1000;
//how many seconds late are we, minimum 1 //how many seconds late are we, minimum 1
factor = factor / 1000 +1; factor = factor / 1000 +1;
//reduce the counters by that mouch //reduce the counters by that mouch
//if we can assume that the cycle time (factor) is fairly constant //if we can assume that the cycle time (factor) is fairly constant
//and if the remainder is less than cycle time * 2 //and if the remainder is less than cycle time * 2
//do it early instead of late //do it early instead of late
if(_renewInSec < factor*2 ) if(_renewInSec < factor*2 )
_renewInSec = 0; _renewInSec = 0;
else else
_renewInSec -= factor; _renewInSec -= factor;
if(_rebindInSec < factor*2 ) if(_rebindInSec < factor*2 )
_rebindInSec = 0; _rebindInSec = 0;
else else
_rebindInSec -= factor; _rebindInSec -= factor;
} }
//if we have a lease but should renew, do it //if we have a lease but should renew, do it
if (_dhcp_state == STATE_DHCP_LEASED && _renewInSec <=0){ if (_dhcp_state == STATE_DHCP_LEASED && _renewInSec <=0){
_dhcp_state = STATE_DHCP_REREQUEST; _dhcp_state = STATE_DHCP_REREQUEST;
rc = 1 + request_DHCP_lease(); rc = 1 + request_DHCP_lease();
} }
//if we have a lease or is renewing but should bind, do it //if we have a lease or is renewing but should bind, do it
if( (_dhcp_state == STATE_DHCP_LEASED || _dhcp_state == STATE_DHCP_START) && _rebindInSec <=0){ if( (_dhcp_state == STATE_DHCP_LEASED || _dhcp_state == STATE_DHCP_START) && _rebindInSec <=0){
//this should basically restart completely //this should basically restart completely
_dhcp_state = STATE_DHCP_START; _dhcp_state = STATE_DHCP_START;
reset_DHCP_lease(); reset_DHCP_lease();
rc = 3 + request_DHCP_lease(); rc = 3 + request_DHCP_lease();
} }
} }
else{ else{
_secTimeout = snow + 1000; _secTimeout = snow + 1000;
} }
_lastCheck = now; _lastCheck = now;
return rc; return rc;
} }
IPAddress DhcpClass::getLocalIp() IPAddress DhcpClass::getLocalIp()
{ {
return IPAddress(_dhcpLocalIp); return IPAddress(_dhcpLocalIp);
} }
IPAddress DhcpClass::getSubnetMask() IPAddress DhcpClass::getSubnetMask()
{ {
return IPAddress(_dhcpSubnetMask); return IPAddress(_dhcpSubnetMask);
} }
IPAddress DhcpClass::getGatewayIp() IPAddress DhcpClass::getGatewayIp()
{ {
return IPAddress(_dhcpGatewayIp); return IPAddress(_dhcpGatewayIp);
} }
IPAddress DhcpClass::getDhcpServerIp() IPAddress DhcpClass::getDhcpServerIp()
{ {
return IPAddress(_dhcpDhcpServerIp); return IPAddress(_dhcpDhcpServerIp);
} }
IPAddress DhcpClass::getDnsServerIp() IPAddress DhcpClass::getDnsServerIp()
{ {
return IPAddress(_dhcpDnsServerIp); return IPAddress(_dhcpDnsServerIp);
} }
void DhcpClass::printByte(char * buf, uint8_t n ) { void DhcpClass::printByte(char * buf, uint8_t n ) {
char *str = &buf[1]; char *str = &buf[1];
buf[0]='0'; buf[0]='0';
do { do {
unsigned long m = n; unsigned long m = n;
n /= 16; n /= 16;
char c = m - 16 * n; char c = m - 16 * n;
*str-- = c < 10 ? c + '0' : c + 'A' - 10; *str-- = c < 10 ? c + '0' : c + 'A' - 10;
} while(n); } while(n);
} }
+178 -178
View File
@@ -1,178 +1,178 @@
// DHCP Library v0.3 - April 25, 2009 // DHCP Library v0.3 - April 25, 2009
// Author: Jordan Terrell - blog.jordanterrell.com // Author: Jordan Terrell - blog.jordanterrell.com
#ifndef Dhcp_h #ifndef Dhcp_h
#define Dhcp_h #define Dhcp_h
#include "UIPUdp.h" #include "UIPUdp.h"
/* DHCP state machine. */ /* DHCP state machine. */
#define STATE_DHCP_START 0 #define STATE_DHCP_START 0
#define STATE_DHCP_DISCOVER 1 #define STATE_DHCP_DISCOVER 1
#define STATE_DHCP_REQUEST 2 #define STATE_DHCP_REQUEST 2
#define STATE_DHCP_LEASED 3 #define STATE_DHCP_LEASED 3
#define STATE_DHCP_REREQUEST 4 #define STATE_DHCP_REREQUEST 4
#define STATE_DHCP_RELEASE 5 #define STATE_DHCP_RELEASE 5
#define DHCP_FLAGSBROADCAST 0x8000 #define DHCP_FLAGSBROADCAST 0x8000
/* UDP port numbers for DHCP */ /* UDP port numbers for DHCP */
#define DHCP_SERVER_PORT 67 /* from server to client */ #define DHCP_SERVER_PORT 67 /* from server to client */
#define DHCP_CLIENT_PORT 68 /* from client to server */ #define DHCP_CLIENT_PORT 68 /* from client to server */
/* DHCP message OP code */ /* DHCP message OP code */
#define DHCP_BOOTREQUEST 1 #define DHCP_BOOTREQUEST 1
#define DHCP_BOOTREPLY 2 #define DHCP_BOOTREPLY 2
/* DHCP message type */ /* DHCP message type */
#define DHCP_DISCOVER 1 #define DHCP_DISCOVER 1
#define DHCP_OFFER 2 #define DHCP_OFFER 2
#define DHCP_REQUEST 3 #define DHCP_REQUEST 3
#define DHCP_DECLINE 4 #define DHCP_DECLINE 4
#define DHCP_ACK 5 #define DHCP_ACK 5
#define DHCP_NAK 6 #define DHCP_NAK 6
#define DHCP_RELEASE 7 #define DHCP_RELEASE 7
#define DHCP_INFORM 8 #define DHCP_INFORM 8
#define DHCP_HTYPE10MB 1 #define DHCP_HTYPE10MB 1
#define DHCP_HTYPE100MB 2 #define DHCP_HTYPE100MB 2
#define DHCP_HLENETHERNET 6 #define DHCP_HLENETHERNET 6
#define DHCP_HOPS 0 #define DHCP_HOPS 0
#define DHCP_SECS 0 #define DHCP_SECS 0
#define MAGIC_COOKIE 0x63825363 #define MAGIC_COOKIE 0x63825363
#define MAX_DHCP_OPT 16 #define MAX_DHCP_OPT 16
#define HOST_NAME "ENC28J" #define HOST_NAME "ENC28J"
#define DEFAULT_LEASE (900) //default lease time in seconds #define DEFAULT_LEASE (900) //default lease time in seconds
#define DHCP_CHECK_NONE (0) #define DHCP_CHECK_NONE (0)
#define DHCP_CHECK_RENEW_FAIL (1) #define DHCP_CHECK_RENEW_FAIL (1)
#define DHCP_CHECK_RENEW_OK (2) #define DHCP_CHECK_RENEW_OK (2)
#define DHCP_CHECK_REBIND_FAIL (3) #define DHCP_CHECK_REBIND_FAIL (3)
#define DHCP_CHECK_REBIND_OK (4) #define DHCP_CHECK_REBIND_OK (4)
enum enum
{ {
padOption = 0, padOption = 0,
subnetMask = 1, subnetMask = 1,
timerOffset = 2, timerOffset = 2,
routersOnSubnet = 3, routersOnSubnet = 3,
/* timeServer = 4, /* timeServer = 4,
nameServer = 5,*/ nameServer = 5,*/
dns = 6, dns = 6,
/*logServer = 7, /*logServer = 7,
cookieServer = 8, cookieServer = 8,
lprServer = 9, lprServer = 9,
impressServer = 10, impressServer = 10,
resourceLocationServer = 11,*/ resourceLocationServer = 11,*/
hostName = 12, hostName = 12,
/*bootFileSize = 13, /*bootFileSize = 13,
meritDumpFile = 14,*/ meritDumpFile = 14,*/
domainName = 15, domainName = 15,
/*swapServer = 16, /*swapServer = 16,
rootPath = 17, rootPath = 17,
extentionsPath = 18, extentionsPath = 18,
IPforwarding = 19, IPforwarding = 19,
nonLocalSourceRouting = 20, nonLocalSourceRouting = 20,
policyFilter = 21, policyFilter = 21,
maxDgramReasmSize = 22, maxDgramReasmSize = 22,
defaultIPTTL = 23, defaultIPTTL = 23,
pathMTUagingTimeout = 24, pathMTUagingTimeout = 24,
pathMTUplateauTable = 25, pathMTUplateauTable = 25,
ifMTU = 26, ifMTU = 26,
allSubnetsLocal = 27, allSubnetsLocal = 27,
broadcastAddr = 28, broadcastAddr = 28,
performMaskDiscovery = 29, performMaskDiscovery = 29,
maskSupplier = 30, maskSupplier = 30,
performRouterDiscovery = 31, performRouterDiscovery = 31,
routerSolicitationAddr = 32, routerSolicitationAddr = 32,
staticRoute = 33, staticRoute = 33,
trailerEncapsulation = 34, trailerEncapsulation = 34,
arpCacheTimeout = 35, arpCacheTimeout = 35,
ethernetEncapsulation = 36, ethernetEncapsulation = 36,
tcpDefaultTTL = 37, tcpDefaultTTL = 37,
tcpKeepaliveInterval = 38, tcpKeepaliveInterval = 38,
tcpKeepaliveGarbage = 39, tcpKeepaliveGarbage = 39,
nisDomainName = 40, nisDomainName = 40,
nisServers = 41, nisServers = 41,
ntpServers = 42, ntpServers = 42,
vendorSpecificInfo = 43, vendorSpecificInfo = 43,
netBIOSnameServer = 44, netBIOSnameServer = 44,
netBIOSdgramDistServer = 45, netBIOSdgramDistServer = 45,
netBIOSnodeType = 46, netBIOSnodeType = 46,
netBIOSscope = 47, netBIOSscope = 47,
xFontServer = 48, xFontServer = 48,
xDisplayManager = 49,*/ xDisplayManager = 49,*/
dhcpRequestedIPaddr = 50, dhcpRequestedIPaddr = 50,
dhcpIPaddrLeaseTime = 51, dhcpIPaddrLeaseTime = 51,
/*dhcpOptionOverload = 52,*/ /*dhcpOptionOverload = 52,*/
dhcpMessageType = 53, dhcpMessageType = 53,
dhcpServerIdentifier = 54, dhcpServerIdentifier = 54,
dhcpParamRequest = 55, dhcpParamRequest = 55,
/*dhcpMsg = 56, /*dhcpMsg = 56,
dhcpMaxMsgSize = 57,*/ dhcpMaxMsgSize = 57,*/
dhcpT1value = 58, dhcpT1value = 58,
dhcpT2value = 59, dhcpT2value = 59,
/*dhcpClassIdentifier = 60,*/ /*dhcpClassIdentifier = 60,*/
dhcpClientIdentifier = 61, dhcpClientIdentifier = 61,
endOption = 255 endOption = 255
}; };
typedef struct _RIP_MSG_FIXED typedef struct _RIP_MSG_FIXED
{ {
uint8_t op; uint8_t op;
uint8_t htype; uint8_t htype;
uint8_t hlen; uint8_t hlen;
uint8_t hops; uint8_t hops;
uint32_t xid; uint32_t xid;
uint16_t secs; uint16_t secs;
uint16_t flags; uint16_t flags;
uint8_t ciaddr[4]; uint8_t ciaddr[4];
uint8_t yiaddr[4]; uint8_t yiaddr[4];
uint8_t siaddr[4]; uint8_t siaddr[4];
uint8_t giaddr[4]; uint8_t giaddr[4];
uint8_t chaddr[6]; uint8_t chaddr[6];
}RIP_MSG_FIXED; }RIP_MSG_FIXED;
class DhcpClass { class DhcpClass {
private: private:
uint32_t _dhcpInitialTransactionId; uint32_t _dhcpInitialTransactionId;
uint32_t _dhcpTransactionId; uint32_t _dhcpTransactionId;
uint8_t _dhcpMacAddr[6]; uint8_t _dhcpMacAddr[6];
uint8_t _dhcpLocalIp[4]; uint8_t _dhcpLocalIp[4];
uint8_t _dhcpSubnetMask[4]; uint8_t _dhcpSubnetMask[4];
uint8_t _dhcpGatewayIp[4]; uint8_t _dhcpGatewayIp[4];
uint8_t _dhcpDhcpServerIp[4]; uint8_t _dhcpDhcpServerIp[4];
uint8_t _dhcpDnsServerIp[4]; uint8_t _dhcpDnsServerIp[4];
uint32_t _dhcpLeaseTime; uint32_t _dhcpLeaseTime;
uint32_t _dhcpT1, _dhcpT2; uint32_t _dhcpT1, _dhcpT2;
signed long _renewInSec; signed long _renewInSec;
signed long _rebindInSec; signed long _rebindInSec;
signed long _lastCheck; signed long _lastCheck;
unsigned long _timeout; unsigned long _timeout;
unsigned long _responseTimeout; unsigned long _responseTimeout;
unsigned long _secTimeout; unsigned long _secTimeout;
uint8_t _dhcp_state; uint8_t _dhcp_state;
UIPUDP _dhcpUdpSocket; UIPUDP _dhcpUdpSocket;
int request_DHCP_lease(); int request_DHCP_lease();
void reset_DHCP_lease(); void reset_DHCP_lease();
void presend_DHCP(); void presend_DHCP();
void send_DHCP_MESSAGE(uint8_t, uint16_t); void send_DHCP_MESSAGE(uint8_t, uint16_t);
void printByte(char *, uint8_t); void printByte(char *, uint8_t);
uint8_t parseDHCPResponse(unsigned long responseTimeout, uint32_t& transactionId); uint8_t parseDHCPResponse(unsigned long responseTimeout, uint32_t& transactionId);
public: public:
IPAddress getLocalIp(); IPAddress getLocalIp();
IPAddress getSubnetMask(); IPAddress getSubnetMask();
IPAddress getGatewayIp(); IPAddress getGatewayIp();
IPAddress getDhcpServerIp(); IPAddress getDhcpServerIp();
IPAddress getDnsServerIp(); IPAddress getDnsServerIp();
int beginWithDHCP(uint8_t *, unsigned long timeout = 60000, unsigned long responseTimeout = 4000); int beginWithDHCP(uint8_t *, unsigned long timeout = 60000, unsigned long responseTimeout = 4000);
int checkLease(); int checkLease();
}; };
#endif #endif
+41 -41
View File
@@ -1,41 +1,41 @@
// Arduino DNS client for Enc28J60-based Ethernet shield // Arduino DNS client for Enc28J60-based Ethernet shield
// (c) Copyright 2009-2010 MCQN Ltd. // (c) Copyright 2009-2010 MCQN Ltd.
// Released under Apache License, version 2.0 // Released under Apache License, version 2.0
#ifndef DNSClient_h #ifndef DNSClient_h
#define DNSClient_h #define DNSClient_h
#include <UIPUdp.h> #include <UIPUdp.h>
class DNSClient class DNSClient
{ {
public: public:
// ctor // ctor
void begin(const IPAddress& aDNSServer); void begin(const IPAddress& aDNSServer);
/** Convert a numeric IP address string into a four-byte IP address. /** Convert a numeric IP address string into a four-byte IP address.
@param aIPAddrString IP address to convert @param aIPAddrString IP address to convert
@param aResult IPAddress structure to store the returned IP address @param aResult IPAddress structure to store the returned IP address
@result 1 if aIPAddrString was successfully converted to an IP address, @result 1 if aIPAddrString was successfully converted to an IP address,
else error code else error code
*/ */
int inet_aton(const char *aIPAddrString, IPAddress& aResult); int inet_aton(const char *aIPAddrString, IPAddress& aResult);
/** Resolve the given hostname to an IP address. /** Resolve the given hostname to an IP address.
@param aHostname Name to be resolved @param aHostname Name to be resolved
@param aResult IPAddress structure to store the returned IP address @param aResult IPAddress structure to store the returned IP address
@result 1 if aIPAddrString was successfully converted to an IP address, @result 1 if aIPAddrString was successfully converted to an IP address,
else error code else error code
*/ */
int getHostByName(const char* aHostname, IPAddress& aResult); int getHostByName(const char* aHostname, IPAddress& aResult);
protected: protected:
uint16_t BuildRequest(const char* aName); uint16_t BuildRequest(const char* aName);
uint16_t ProcessResponse(uint16_t aTimeout, IPAddress& aAddress); uint16_t ProcessResponse(uint16_t aTimeout, IPAddress& aAddress);
IPAddress iDNSServer; IPAddress iDNSServer;
uint16_t iRequestId; uint16_t iRequestId;
UIPUDP iUdp; UIPUDP iUdp;
}; };
#endif #endif