fixed crlf for project
This commit is contained in:
@@ -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
File diff suppressed because it is too large
Load Diff
+194
-194
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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(¤t);
|
set_time(¤t);
|
||||||
|
|
||||||
// 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
@@ -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
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -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
@@ -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
@@ -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.
|
||||||
}
|
}
|
||||||
@@ -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)
|
||||||
###################################
|
###################################
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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() {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -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.
|
||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user