From 398a9cfc5b21a0b36d8505590ede62456234d481 Mon Sep 17 00:00:00 2001 From: guohui Date: Wed, 30 Jul 2014 11:22:11 +0800 Subject: [PATCH] First commit --- Jump2DFU/Jump2DFU.cpp.hex | 844 ++++++++++++++++++ Jump2DFU/Jump2DFU.ino | 26 + README.md | 34 +- Release/Caterina-BlendMicro.hex | 258 ++++++ Source/ble-caterina/BLE/aci.h | 666 ++++++++++++++ Source/ble-caterina/BLE/aci_cmds.h | 433 +++++++++ Source/ble-caterina/BLE/aci_evts.h | 397 ++++++++ .../ble-caterina/BLE/aci_protocol_defines.h | 187 ++++ Source/ble-caterina/BLE/aci_setup.c | 163 ++++ Source/ble-caterina/BLE/aci_setup.h | 44 + Source/ble-caterina/BLE/acilib.h | 61 ++ Source/ble-caterina/BLE/acilib_defs.h | 37 + Source/ble-caterina/BLE/acilib_if.h | 65 ++ Source/ble-caterina/BLE/dfu.c | 401 +++++++++ Source/ble-caterina/BLE/dfu.h | 69 ++ Source/ble-caterina/BLE/hal_aci_tl.c | 234 +++++ Source/ble-caterina/BLE/hal_aci_tl.h | 125 +++ Source/ble-caterina/BLE/hal_platform.h | 37 + Source/ble-caterina/BLE/lib_aci.c | 293 ++++++ Source/ble-caterina/BLE/lib_aci.h | 220 +++++ Source/ble-caterina/BLE/services.h | 176 ++++ Source/ble-caterina/Caterina.c | 310 +++++++ Source/ble-caterina/Caterina.h | 90 ++ Source/ble-caterina/Descriptors.h | 96 ++ Source/ble-caterina/Makefile | 744 +++++++++++++++ 25 files changed, 6008 insertions(+), 2 deletions(-) create mode 100644 Jump2DFU/Jump2DFU.cpp.hex create mode 100644 Jump2DFU/Jump2DFU.ino create mode 100644 Release/Caterina-BlendMicro.hex create mode 100644 Source/ble-caterina/BLE/aci.h create mode 100644 Source/ble-caterina/BLE/aci_cmds.h create mode 100644 Source/ble-caterina/BLE/aci_evts.h create mode 100644 Source/ble-caterina/BLE/aci_protocol_defines.h create mode 100644 Source/ble-caterina/BLE/aci_setup.c create mode 100644 Source/ble-caterina/BLE/aci_setup.h create mode 100644 Source/ble-caterina/BLE/acilib.h create mode 100644 Source/ble-caterina/BLE/acilib_defs.h create mode 100644 Source/ble-caterina/BLE/acilib_if.h create mode 100644 Source/ble-caterina/BLE/dfu.c create mode 100644 Source/ble-caterina/BLE/dfu.h create mode 100644 Source/ble-caterina/BLE/hal_aci_tl.c create mode 100644 Source/ble-caterina/BLE/hal_aci_tl.h create mode 100644 Source/ble-caterina/BLE/hal_platform.h create mode 100644 Source/ble-caterina/BLE/lib_aci.c create mode 100644 Source/ble-caterina/BLE/lib_aci.h create mode 100644 Source/ble-caterina/BLE/services.h create mode 100644 Source/ble-caterina/Caterina.c create mode 100644 Source/ble-caterina/Caterina.h create mode 100644 Source/ble-caterina/Descriptors.h create mode 100644 Source/ble-caterina/Makefile diff --git a/Jump2DFU/Jump2DFU.cpp.hex b/Jump2DFU/Jump2DFU.cpp.hex new file mode 100644 index 0000000..eb7c582 --- /dev/null +++ b/Jump2DFU/Jump2DFU.cpp.hex @@ -0,0 +1,844 @@ +:100000000C9499030C94EF0E0C941C0F0C94490F54 +:100010000C94760F0C94C1030C94C1030C94A30FA1 +:100020000C94C1030C94C1030C9460160C94E71655 +:100030000C94C1030C94C1030C94C1030C94C10330 +:100040000C94C1030C94C1030C94C1030C94C10320 +:100050000C94C1030C94C1030C94C1030C94D00FF5 +:100060000C94C1030C94C1030C94C1030C94C10300 +:100070000C94C1030C94C1030C94C1030C94C103F0 +:100080000C94C1030C94C1030C94C1030C94C103E0 +:100090000C94C1030C94C1030C94C1030C94C103D0 +:1000A0000C94C1030C94C1030C94C103002C2000D8 +:1000B0004164766572746973696E672073746172E6 +:1000C000746564004857206572726F723A20002090 +:1000D0002050697065204572726F7220436F6465AD +:1000E0003A203078004143492045767420506970A9 +:1000F00065204572726F723A205069706520233A0C +:100100000050697065204E756D6265723A2000413D +:1001100064766572746973696E6720737461727452 +:1001200065640045767420446973636F6E6E656321 +:100130007465642F4164766572746973696E6720B3 +:1001400074696D6564206F757400457674206C6900 +:100150006E6B20636F6E6E656374696F6E20696E7F +:1001600074657276616C206368616E6765640045D2 +:1001700076742050697065205374617475730045FE +:10018000767420436F6E6E656374656400457674A3 +:1001900020436D6420726573706F6E653A205374EE +:1001A00061747573200041434920436F6D6D616E2A +:1001B0006420004164766572746973696E672073A8 +:1001C0007461727465640045767420446576696371 +:1001D0006520537461727465643A205374616E646F +:1001E00062790045767420446576696365205374AE +:1001F00061727465643A2053657475700000070677 +:1002000000000302420700000000000000000000A0 +:100210000000000000000000000000000000001FBF +:1002200006100000000000000005000501010000AC +:100230000600009000000000000000000000000028 +:100240001F06101C0002000000000000000000005B +:10025000000000000000001000000010039001FFEB +:10026000001F061038FFFF025800050000000000C4 +:100270000000140000001000000004000000000056 +:1002800000000506105400000000000000000000FF +:10029000000000000000000000000000000000005E +:1002A0000000001F062000040402020001280001D3 +:1002B00000180404050500022803010E0300002AAB +:1002C00004140A001F06201C0A00032A0001424CE5 +:1002D0004520536869656C6404040505000428031F +:1002E00001020500001F062038012A06040302004F +:1002F000052A010100000404050500062803010287 +:100300000700042A06001F06205404090800072AD3 +:1003100004010600120000000A00040402020008A2 +:10032000280001011804001F0620700405050009BB +:10033000280301220A00052A26040504000A2A05CA +:1003400001000000004614001F06208C0302000B71 +:10035000290201000004041010000C2800011E9462 +:100360008DF1483194BA754C001F0620A83E50000C +:10037000003D7104041313000D280301040E001E38 +:10038000948DF1483194BA754C001F0620C43E503C +:1003900003003D7144101400000E00030200000031 +:1003A00000000000000000000000001F0620E00028 +:1003B00000000000000004041313000F28030110C4 +:1003C00010001E948DF1483194BA75001F0620FC70 +:1003D0004C3E5002003D7114001400001000020257 +:1003E000000000000000000000000000001F0621C7 +:1003F000180000000000000000461403020011294C +:1004000002010000040402020012280001001F067D +:1004100021340A18040405050013280301021400FE +:10042000272A0404090100142A27010A0000000AEF +:100430000621500000000000000000000000000045 +:1004400000000000000000000000000000000000AC +:100450001F0640002A0001008004000300002A0556 +:1004600001000404000A000B000302000804000E4F +:10047000001906401C0000000202000204001000E7 +:10048000112A270100800400140000000000000071 +:100490000000130650001E948DF1483194BA754C3B +:1004A0003E5000003D710000000000000000000010 +:1004B00000000012066000000000000000000000C4 +:1004C000000000000000000000000000000000002C +:1004D000000000000606F000033D6C000000000074 +:1004E000000000000000000000000000000000000C +:1004F0000000000000000000240027002A002D005A +:10050000300000000000250028002B002E003100E4 +:10051000000000002300260029002C002F00040406 +:10052000040404030405020202020403020202029C +:100530000606060606060404020202040408020176 +:10054000104080401020408040800802040180401C +:10055000201002011080102040400000000200081E +:100560000E0000030401000B00000000000000006A +:100570000000000000000000070605040100080A52 +:100580000B0C0D09080B0002020201000904000017 +:1005900001020200000524001001052401010104EC +:1005A0002402060524060001070581031000400906 +:1005B000040100020A0000000705020240000007D3 +:1005C0000583024000000403090422035500530080 +:1005D0004200200049004F00200042006F006100EF +:1005E0007200640020002000200020001803550045 +:1005F0006E006B006E006F0077006E002000200020 +:10060000200020001201000200000040EB0304243F +:100610000001010200011201000202000040EB0390 +:10062000042400010102000100C18081C10501090B +:1006300002A1010901A1008501050919012903157C +:10064000002501950375018102950175058103055A +:10065000010930093109381581257F750895038115 +:1006600006C0C005010906A1018502050719E02998 +:10067000E71500250175019508810295017508812E +:10068000039506750815002565050719002965817C +:1006900000C009040200010300000009210101005B +:1006A00001226500070584034000010000000000EE +:1006B0000000002A2B2800000000000000000000BD +:1006C00000000000000000000000002C9EB4A0A16B +:1006D000A2A434A6A7A5AE362D3738271E1F202189 +:1006E0002223242526B333B62EB7B89F8485868768 +:1006F00088898A8B8C8D8E8F909192939495969702 +:1007000098999A9B9C9D2F3130A3AD35040506071F +:1007100008090A0B0C0D0E0F1011121314151617E1 +:1007200018191A1B1C1DAFB1B0B500000D129A1597 +:100730006A1811241FBECFEFDAE0DEBFCDBF12E092 +:10074000A0E0B1E0E8E7F3E302C005900D92A23229 +:10075000B107D9F714E0A2E2B2E001C01D92A73BB5 +:10076000B107E1F717E0C2E3D7E004C02297FE012A +:100770000E94B619CC32D107C9F70E94D8120C9446 +:10078000BA190C940000FB01DC0102C005900D9227 +:1007900041505040D8F70895FB01DC0102C00190A0 +:1007A0000D9241505040D8F708950E94580B88236D +:1007B000B9F00E94340B8F3F910591F487E797E7DA +:1007C000909301088093000828E088E190E00FB63C +:1007D000F894A895809360000FBE20936000FFCF2F +:1007E0000E94510D08950E94000E0895882319F467 +:1007F0008CB5806202C08CB58F7D8CBD08959CB590 +:10080000937F982B9CBD08952CB5382F33702C7F87 +:10081000322B3CBD2DB590E09595879595958795A4 +:1008200081702E7F822B8DBD089581E161E00E9451 +:10083000601181E161E00E94D3108CB580618CBDB4 +:100840008CB580648CBD8FE061E00E94D31080E1A4 +:1008500061E00E94D3100895FC0181E0808389E06B +:1008600081830895FC01DB0185E080838FE0818333 +:1008700011968C91119783838C91828313968C911E +:100880001397858312968C9184830895FC0181E0EF +:1008900080838EE081830895FC0181E0808383E181 +:1008A00081830895DC014E5F4C93425085E111969F +:1008B0008C931197FB01819112968C93129713964A +:1008C000CD01BF0150E00E94CC030895DC014E5FD2 +:1008D0004C9342508DE011968C931197FB018191BE +:1008E00012968C9312971396CD01BF0150E00E948F +:1008F000CC0308951F93CF93DF93EC01CB57DF4FC9 +:100900001881C558D04031F480E091E069EA70E088 +:100910000E94530E30E0812F90E00196837090701A +:10092000CC57DF4F2881281709F431E0832FDF915E +:10093000CF911F910895CF93DF93EC01009731F48D +:1009400080E091E060E970E00E94530EF8947894A2 +:1009500030E0CB57DF4F888190E001968370907034 +:10096000FE012291281709F431E0832FDF91CF9106 +:100970000895CF93DF93EC01009731F480E091E08C +:1009800066E870E00E94530E20E0FE01EB57FF4F37 +:10099000CC57DF4F98818081981709F421E0822F8E +:1009A000DF91CF910895CF93DF93EC01009731F45D +:1009B00080E091E067E770E00E94530EF89478942D +:1009C00020E0FE01EB57FF4FCC57DF4F988180812D +:1009D000981709F421E0822FDF91CF910895CF93EA +:1009E000DF93EC01009731F480E091E062E270E087 +:1009F0000E94530ECC57DF4F19921882C558D04031 +:100A0000FE0180E0118212828F5FB1968430D1F7AF +:100A1000DF91CF9108950F931F93CF93DF93EC0154 +:100A20008B01009731F480E091E060EB70E00E9470 +:100A3000530E0115110531F480E091E061EB70E097 +:100A40000E94530ECE010E94D304882311F080E04F +:100A500013C0CC57DF4F8881FE01E458F04021E2FB +:100A6000829FC0011124D801E80FF91F81E2019093 +:100A70000D928150E1F781E0DF91CF911F910F91AD +:100A80000895DF92EF92FF920F931F93CF93DF931E +:100A9000EC017B01FB01D180009731F480E091E013 +:100AA00064E670E00E94530EE114F10431F480E03A +:100AB00091E065E670E00E94530ECE010E947A0438 +:100AC000882311F080E02EC08E010B571F4FF801D4 +:100AD000808190E0FC0125E0EE0FFF1F2A95E1F7F1 +:100AE000E80FF91FEC0FFD1F1082F801208181E251 +:100AF000289F900111242F5F3F4F2C0F3D1FED2D9C +:100B0000F0E03196A7014F5F5F4FC901BA01AF0115 +:100B10000E94CC03F801808190E001968370907070 +:100B2000808381E0DF91CF911F910F91FF90EF9033 +:100B3000DF900895DF92EF92FF920F931F93CF9370 +:100B4000DF93EC017B01FB01D180009731F480E061 +:100B500091E061E570E00E94530EE114F10431F47C +:100B600080E091E062E570E00E94530ECE010E94A9 +:100B70009B04882311F080E02EC08E010B571F4F7D +:100B8000F801808190E0FC0135E0EE0FFF1F3A95FF +:100B9000E1F7E80FF91FEC0FFD1F1082F80120812B +:100BA00081E2289F900111242F5F3F4F2C0F3D1FA2 +:100BB000ED2DF0E03196A7014F5F5F4FC901BA01FB +:100BC000AF010E94CC03F801808190E00196837010 +:100BD0009070808381E0DF91CF911F910F91FF9002 +:100BE000EF90DF9008950F931F93CF93DF93EC0165 +:100BF0008B01009731F480E091E06FE370E00E9498 +:100C0000530E0115110531F480E091E060E470E0CD +:100C10000E94530ECE010E94B904882311F080E097 +:100C20001AC0CC57DF4F9881C458D04081E2989FBA +:100C3000F0011124D801EC0FFD1F01900D9281509D +:100C4000E1F7FE01EC57FF4F808190E00196837041 +:100C50009070808381E0DF91CF911F910F91089573 +:100C60000F931F93CF93DF93EC018B01009731F427 +:100C700080E091E06FE270E00E94530E01151105D3 +:100C800031F480E091E060E370E00E94530ECE0109 +:100C90000E94D304882311F080E01AC0CC57DF4FA4 +:100CA0009881C458D04081E2989FF0011124D80166 +:100CB000EC0FFD1F01900D928150E1F7FE01EC5702 +:100CC000FF4F808190E0019683709070808381E077 +:100CD000DF91CF911F910F910895EF92FF920F93A3 +:100CE0001F93CF93DF938C01EB01FF2481E2E82E69 +:100CF00020C0D8011F96ED91FC9150979E9DC00198 +:100D00001124E80FF91F31964491319750E04E5F5E +:100D10005F4F81E393E0BF010E94C30381E393E04F +:100D20000E94A007882351F088818F5F8883FF2469 +:100D3000F3949881F80181899817D8F28F2DDF916B +:100D4000CF911F910F91FF90EF9008959F92AF92D6 +:100D5000BF92CF92DF92EF92FF920F931F93DF9398 +:100D6000CF930F92CDB7DEB75C0119820E94930931 +:100D7000882311F481E049C081E393E00E94DD09FA +:100D8000882311F082E041C0C5018E010F5F1F4F23 +:100D9000B8010E946D06CC24DD247601902E012F2F +:100DA0000BC08FEFC8168FEFD8068FE0E80680E003 +:100DB000F80610F083E029C00894C11CD11CE11C86 +:100DC000F11C81E393E00E94DD09882351F38091B7 +:100DD0003303843811F085E018C0109135031130C9 +:100DE00021F0123051F084E010C0C501692D702F40 +:100DF0000E946D06CC24DD247601C50161E373E019 +:100E00000E949609123069F680E00F90CF91DF9131 +:100E10001F910F91FF90EF90DF90CF90BF90AF9018 +:100E20009F90089582E292E00E94D3040895FF9279 +:100E30000F931F93CF93DF938C01EB01E0912F036E +:100E4000F0913003818160E00E946011F80181819E +:100E50008EBD0DB407FEFDCF8EB58883F80182816B +:100E60008EBD0DB407FEFDCF5EB55983F8014181FB +:100E7000442349F0242F30E0852F90E08217930718 +:100E800014F4542F5150F52EFFE1F51710F48FE1B3 +:100E9000F82E4C2FD801CE01FC010BC013968C917B +:100EA00013978EBD0DB407FEFDCF8EB582833196AC +:100EB00011968E2F841B8F1588F3E0912F03F091EC +:100EC0003003818161E00E9460118F2DF11081E07B +:100ED000DF91CF911F910F91FF9008950F931F9372 +:100EE000CF93DF93EC01098183E994E0602F4AE01E +:100EF00050E00E942F1483E994E06CE371E00E94BB +:100F0000D11410E0FE01E10FF11D83E994E061814D +:100F100040E150E00E942F1483E994E06DEA70E014 +:100F20000E941B131F5F011768F783E994E06CEAC6 +:100F300070E00E945E13DF91CF911F910F91089591 +:100F40001F93CF93DF93EC018981803210F010E082 +:100F500023C082E292E0BE010E949A05182F8823E6 +:100F6000D9F088EA92E00E949B04882341F4E09142 +:100F70002F03F0913003818160E00E946011809125 +:100F80002E03882349F083E994E06FE371E00E9427 +:100F9000D114CE010E946E07812FDF91CF911F9156 +:100FA0000895E0912F03F091300387818F3F89F1FD +:100FB00061E00E94D310E0912F03F0913003808113 +:100FC000813099F4878161E00E94601164E670E0ED +:100FD00080E090E00E942410E0912F03F091300314 +:100FE000878160E00E9460110895878161E00E941E +:100FF0006011E0912F03F0913003878160E00E943F +:101000006011E0912F03F0913003878161E00E942D +:1010100060110895CF93DF93EC0160932E039093BA +:10102000300380932F030E94150480E00E94F60392 +:101030008E810E94040480E00E94FF0382E292E01D +:101040000E94EF0488EA92E00E94EF048A8162E045 +:101050000E94D310898161E00E94D31088858F3F60 +:1010600019F060E00E94D3100E94D1078C8160E0EB +:101070000E9460118B8160E00E946011898161E0B3 +:101080000E9460118D8160E00E9460116EE170E04D +:1010900080E090E00E9424108A85882339F08B85B7 +:1010A00069E578E040E050E00E94780EDF91CF9152 +:1010B0000895DF93CF93CDB7DEB7C254D0400FB6BB +:1010C000F894DEBF0FBECDBF109264001092650091 +:1010D00082E292E0BE016F5F7F4F0E94F30588239A +:1010E00011F419821A82CE010196BE016E5D7F4F06 +:1010F0000E94170788EA92E00E947A04882371F41C +:1011000082E292E00E94B904882341F4E0912F0327 +:10111000F0913003818160E00E9460118BA18823EF +:10112000B9F088EA92E0BE016E5D7F4F0E944105F2 +:10113000882309F4FFCF88EA92E00E947A0488238A +:1011400039F0E0912F03F091300383850E94CD0E9A +:10115000CE5BDF4F0FB6F894DEBF0FBECDBFCF9191 +:10116000DF910895DF93CF93CDB7DEB7C254D0405F +:101170000FB6F894DEBF0FBECDBF88EA92E00E94A2 +:101180009B04882309F04BC0E0912F03F0913003BA +:1011900082810E949311019779F482E292E00E9489 +:1011A000D3048823E1F5E0912F03F091300381818E +:1011B00060E00E94601133C082E292E0BE016F5F86 +:1011C0007F4F0E943006882311F419821A82CE01C3 +:1011D0000196BE016E5D7F4F0E94170788EA92E07C +:1011E0000E949B04882371F482E292E00E94D3045F +:1011F000882341F4E0912F03F0913003818160E076 +:101200000E9460118BA1882351F088EA92E0BE0110 +:101210006E5D7F4F0E949A05882309F4FFCFCE5B55 +:10122000DF4F0FB6F894DEBF0FBECDBFCF91DF9179 +:1012300008951F93CF93DF93EC01E0912F03F0917A +:1012400030038285882341F488EA92E00E949B045F +:10125000882311F40E94B20888EA92E00E949B045D +:10126000182F88EA92E0BE010E943006882391F18F +:1012700080912E03882349F083E994E061E471E0D2 +:101280000E94D114CE010E946E07112371F0E091EB +:101290002F03F09130038285882339F0838569E537 +:1012A00078E040E050E00E94780E88EA92E00E94E8 +:1012B0009B04882371F482E292E00E94D304882385 +:1012C00041F4E0912F03F0913003818160E00E94AE +:1012D000601181E0DF91CF911F910895CF93DF934B +:1012E000EC01E0912F03F09130038285882311F403 +:1012F0000E94B20888EA92E0BE010E940B05DF91CD +:10130000CF910895262F269526952695FC01E20F6C +:10131000F11D848D90E0677002C0959587956A9560 +:10132000E2F7817008950E94120708950F931F93AA +:10133000CF93DF938C01EB01CB010E941909282F79 +:101340008823A9F18A81883829F0893819F18638EB +:1013500071F512C0DE01F8017C9690E013968C9135 +:10136000139780831B968C911B9780879F5F1196A4 +:101370003196983099F71BC0F8017C9680E0108276 +:1013800010868F5F31968830D1F7F80114A68389D3 +:10139000858B0DC08B819C81F801978B868B8D810D +:1013A0009E81918F808F8F819885938F828F822FDE +:1013B000DF91CF911F910F9108950E946E090895BA +:1013C0000F931F9302E313E0C8010E944C04C8016D +:1013D00001970E94A0071F910F9108951F93DF931B +:1013E000CF93CDB7DEB765970FB6F894DEBF0FBECB +:1013F000CDBF582F142F282F30E0C901880F991F17 +:10140000820F931FE0915A03F0915B03E80FF91FDD +:101410003397818192818230910511F00497C1F454 +:101420001531B0F459839E012E5F3F4FC901412F02 +:1014300050E00E94CC0382E393E0BE016F5F7F4FD8 +:10144000412F0E94520481E393E00E94A00701C053 +:1014500080E065960FB6F894DEBF0FBECDBFCF918A +:10146000DF911F9108950F931F93DF93CF9300D0C7 +:1014700000D0CDB7DEB79A8389837C836B8302E388 +:1014800013E0C801BE016F5F7F4F0E943204C801A4 +:1014900001970E94A0070F900F900F900F90CF918F +:1014A000DF911F910F9108951F93DF93CF93CDB7D5 +:1014B000DEB765970FB6F894DEBF0FBECDBF122F13 +:1014C000262F30E0C901880F991F820F931FE091EA +:1014D0005A03F0915B03E80FF91F33978081813045 +:1014E000C9F41531B8F469839E012E5F3F4FC901DD +:1014F000BA01412F50E00E94CC0382E393E0BE0189 +:101500006F5F7F4F412F0E94660481E393E00E944A +:10151000A00701C080E065960FB6F894DEBF0FBE4D +:10152000CDBFCF91DF911F9108950F931F9302E3D9 +:1015300013E0C8010E942C04C80101970E94A00773 +:101540001F910F9108950F931F9302E313E0C801B9 +:101550000E944604C80101970E94A0071F910F91A5 +:101560000895CF93DF93EC018881813009F049C061 +:1015700064E670E080E090E00E9424100E94A30ADC +:10158000CE0161E373E00E9496098823C9F380913C +:1015900033038438A9F780913503833861F484E0FC +:1015A0008093320381E88093330382E08093340395 +:1015B000109235030EC0882379F484E080933203BF +:1015C00081E88093330383E08093340310923503E2 +:1015D00082E0809336030FC0823899F484E08093D0 +:1015E000320381E88093330381E0809334031092C7 +:1015F00035031092360388EA92E061E373E00E94BB +:101600009A05DF91CF910895CF93DF93EC01FC0110 +:101610007C96A2E5B3E0108210861D92319683E09D +:10162000AA35B807C1F710925C03109260031092BC +:101630005F0310925D0310925E03109261038C852C +:101640009D8590935B0380935A038F85988990932F +:10165000630380936203CE010E940A08CE010E94B8 +:10166000B10ADF91CF9108954091F803442319F412 +:101670002FEF3FEF1BC08091E6019091E701895366 +:10168000944031F489EF93E09093E7018093E60171 +:10169000E091E601F091E7018191282F30E0F0938D +:1016A000E701E093E60141504093F803C901089532 +:1016B0008091F80308951F9385E693E064ED73E04D +:1016C0000E949609882309F49DC18091D60386382B +:1016D00009F4C7C0873880F4833809F45FC18438BF +:1016E00020F4813809F0CFC11AC0843809F459C0F8 +:1016F000853809F0C8C185C08A3809F4FCC08B3828 +:1017000038F4883809F48FC0893809F0BCC1A4C006 +:101710008C3809F4BCC08D3809F0B5C10BC180917B +:10172000D903809378038091D703823021F08330EE +:1017300009F0A9C10AC083E994E063EE71E00E9458 +:101740005E1381E080933B049EC183E994E067ECE3 +:1017500071E00E945E138091D803882339F064E120 +:1017600070E080E090E00E9424108DC1A9EDB1E00E +:10177000FD0101900020E9F73197EA1BFB0B85E69C +:1017800093E061E0AD012E2F0E94540A84EB90E0BB +:1017900060E570E00E94330A83E994E063EB71E056 +:1017A0002EC18091D8038823F1F083E994E066EAA2 +:1017B00071E00E941B136091D70383E994E070E00D +:1017C00040E150E00E94B21483E994E06DE871E0DA +:1017D0000E941B136091D80383E994E070E040E11C +:1017E00050E00E94B2148091D703893009F04BC1B8 +:1017F00085E693E065E049ED53E029E00E94540A54 +:1018000042C181E08093F60383E994E06FE771E0E1 +:101810000E945E131092F7038091780380937A03FD +:101820000E94950A30C183E994E06FE671E00E945E +:101830005E1385E693E064E00E948209882309F440 +:1018400022C18091F703882309F01DC10E94E0099D +:1018500081E08093F70317C183E994E06AE471E0C3 +:10186000CEC01092F60381E08093D30383E994E025 +:1018700063E271E00E945E138EE190E060E570E04B +:101880000E94330A83E994E06FE071E0B8C083E915 +:1018900094E061E071E00E941B1383E994E06091A1 +:1018A000D7034AE050E00E9441144091F803E091D0 +:1018B000E401F091E501A8EDB3E020E030E00DC0D7 +:1018C000403491F084E0E933F80711F4E9EFF3E0F4 +:1018D0008D9181932F5F3F4F4F5F8091D50390E0B3 +:1018E00002972817390764F34093F803F093E50152 +:1018F000E093E401C8C08091D70390917A03890FE7 +:1019000080937A0383E994E064E471E00E94D11447 +:1019100083E994E06DE571E00E94D11483E994E0DD +:1019200060917A034AE050E00E94411481E0809384 +:10193000D303A9C083E994E065EE70E00E941B1315 +:1019400083E994E06091D7034AE050E00E942F14AD +:1019500083E994E06FEC70E00E941B1383E994E04C +:101960006091D80340E150E00E9441148091D80377 +:10197000823929F080917A038F5F80937A0383E91B +:1019800094E06DE571E00E94D11483E994E06091E8 +:101990007A034AE050E00E94411475C083E994E064 +:1019A00064EC70E00E941B136091D7037091D80320 +:1019B00083E994E04AE050E00E94121410E008C06D +:1019C000EC52FC4F83E994E065810E9424121F5F72 +:1019D000E12FF0E08091D50390E00297E817F90736 +:1019E0007CF383E994E00E943E1384EB90E060E591 +:1019F00070E00E94330A83E994E060EB70E00E949B +:101A00005E1341C080913A04882309F43CC0809160 +:101A10007A008F7780937A0080917B008F7B809310 +:101A20007B001FBEA89584B7877F84BF809160002C +:101A3000886180936000109260008FB780688FBFCC +:101A400085B7806885BF8FEF80937E008DB3887FD8 +:101A50008DBB809168008E7F8093680010926B0030 +:101A60008DEA8093640089E98093650083B7817F64 +:101A7000846083BF83B7816083BF7894889583B780 +:101A80008E7F83BF789480913B04882341F085E664 +:101A900093E00E94A606882311F410923B041F9144 +:101AA00008951F938CB58093640380E00E94F60331 +:101AB00085E00E94040480E00E94FF0385E693E035 +:101AC00064E00E948209882309F493C08091920304 +:101AD000882309F48EC010E045C06D567C4F84E029 +:101AE00044E10E94EE098823A9F083E994E065E7C8 +:101AF00071E00E94D11483E994E064E170E04AE06F +:101B000050E00E949F1483E994E067E971E00E942D +:101B1000D11406C083E994E06CE971E00E94D4140A +:101B20008091920384518093920380917A03815033 +:101B300080937A0383E994E06DE571E00E94D1140B +:101B400083E994E060917A034AE050E00E944114F6 +:101B50001092D30302C00E945B0B8091D3038823B1 +:101B6000D1F31C5E40919203612F70E0453108F083 +:101B7000B4CF6D567C4F84E00E94EE098823A9F013 +:101B800083E994E065E771E00E94D11483E994E071 +:101B9000609192034AE050E00E942F1483E994E0A0 +:101BA00067E971E00E94D11406C083E994E06CE912 +:101BB00071E00E94D4141092920380917A038150B4 +:101BC00080937A0383E994E06DE571E00E94D1147B +:101BD00083E994E060917A034AE050E00E94411466 +:101BE0001092D30302C00E945B0B8091D303882321 +:101BF000D1F30E945B0B809164038CBD1F9108950B +:101C00008CB58093640380E00E94F60385E00E9417 +:101C1000040480E00E94FF0388EE91E09093720339 +:101C20008093710325E0209373038DEF91E09093EF +:101C300075038093740387E18093760310926503A4 +:101C40008091D701809366038091D80180936703C8 +:101C500080E1809368038EE0809369038FE0809336 +:101C60006A0320936B0384E080936C038FEF80936F +:101C70006D0380936E0380913A04882321F081E004 +:101C800080936F0302C010926F0384E0809370030F +:101C900085E693E060E00E94040B809164038CBDB4 +:101CA0000E9415040895EF92FF920F931F938C01E9 +:101CB0007B0183E994E06BEC71E00E94D11483E92D +:101CC00094E0B8010E94D11483E994E062ED71E0E0 +:101CD0000E94D11483E994E0B7014AE050E00E94E9 +:101CE000011483E994E065ED71E00E94D114FFCF07 +:101CF000853008F051C0E82FF0E0EE0FFF1FE45CE4 +:101D0000FB4F71836083823009F1833030F4882384 +:101D100049F0813009F040C00DC0833021F184309A +:101D2000D9F52EC0809169008C7F842B8093690047 +:101D3000E89A089580916900440F551F440F551F7C +:101D4000837F842B80936900E99A089580916900CC +:101D500034E0440F551F3A95E1F78F7C842B809334 +:101D60006900EA9A08958091690026E0440F551FA2 +:101D70002A95E1F78F73842B80936900EB9A08957D +:101D800080916A0094E0440F551F9A95E1F78F7C8B +:101D9000842B80936A00EE9A08958530F8F482309F +:101DA00081F0833028F4882341F0813079F407C032 +:101DB000833049F0843051F408C0E89807C0E998AE +:101DC00005C0EA9803C0EB9801C0EE98E82FF0E058 +:101DD000EE0FFF1FE45CFB4F1182108208951F92EB +:101DE0000F920FB60F9211242F933F934F935F934F +:101DF0006F937F938F939F93AF93BF93EF93FF93D3 +:101E000080913C0490913D04892B29F0E0913C04A1 +:101E1000F0913D040995FF91EF91BF91AF919F9192 +:101E20008F917F916F915F914F913F912F910F9083 +:101E30000FBE0F901F9018951F920F920FB60F9222 +:101E400011242F933F934F935F936F937F938F93BF +:101E50009F93AF93BF93EF93FF9380913E04909134 +:101E60003F04892B29F0E0913E04F0913F0409954D +:101E7000FF91EF91BF91AF919F918F917F916F9162 +:101E80005F914F913F912F910F900FBE0F901F9038 +:101E900018951F920F920FB60F9211242F933F9314 +:101EA0004F935F936F937F938F939F93AF93BF9362 +:101EB000EF93FF938091400490914104892B29F086 +:101EC000E0914004F09141040995FF91EF91BF9199 +:101ED000AF919F918F917F916F915F914F913F91C2 +:101EE0002F910F900FBE0F901F9018951F920F9279 +:101EF0000FB60F9211242F933F934F935F936F93DD +:101F00007F938F939F93AF93BF93EF93FF938091B2 +:101F1000420490914304892B29F0E0914204F0910E +:101F200043040995FF91EF91BF91AF919F918F91DC +:101F30007F916F915F914F913F912F910F900FBEC5 +:101F40000F901F9018951F920F920FB60F921124A9 +:101F50002F933F934F935F936F937F938F939F93B1 +:101F6000AF93BF93EF93FF93809144049091450406 +:101F7000892B29F0E0914404F09145040995FF91E3 +:101F8000EF91BF91AF919F918F917F916F915F91F1 +:101F90004F913F912F910F900FBE0F901F9018956A +:101FA0001F920F920FB60F9211242F933F934F93CE +:101FB0005F936F937F938F939F93AF93BF93209182 +:101FC0004A0430914B0440914C0450914D0470915F +:101FD0004E04DA01C9010296A11DB11D672F6A5F87 +:101FE0006D3730F06D57DA01C9010396A11DB11D9F +:101FF00060934E0480934A0490934B04A0934C0446 +:10200000B0934D048091460490914704A0914804F8 +:10201000B09149040196A11DB11D8093460490938F +:102020004704A0934804B0934904BF91AF919F9196 +:102030008F917F916F915F914F913F912F910F9071 +:102040000FBE0F901F9018959B01AC017FB7F894BD +:102050008091460490914704A0914804B0914904AE +:1020600066B5A89B05C06F3F19F00196A11DB11D73 +:102070007FBFBA2FA92F982F8827860F911DA11DEA +:10208000B11D63E0880F991FAA1FBB1F6A95D1F786 +:10209000BC012DC0FFB7F89480914604909147048D +:1020A000A0914804B0914904E6B5A89B05C0EF3F54 +:1020B00019F00196A11DB11DFFBFBA2FA92F982FAE +:1020C00088278E0F911DA11DB11DE3E0880F991F78 +:1020D000AA1FBB1FEA95D1F7861B970B885E93401A +:1020E000C8F2215030404040504068517C4F21158B +:1020F00031054105510571F60895789484B58260E3 +:1021000084BD84B5816084BD85B5826085BD85B59B +:10211000816085BDEEE6F0E0808181608083E1E84A +:10212000F0E0108280818260808380818160808382 +:10213000E0E8F0E0808181608083E1E9F0E0808187 +:1021400082608083808181608083E0E9F0E080812B +:1021500081608083E1ECF0E0808184608083808115 +:1021600082608083808181608083E3ECF0E0808105 +:1021700081608083E0ECF0E0808182608083E2EC2B +:10218000F0E0808181608083EAE7F0E08081846014 +:102190008083808182608083808181608083808170 +:1021A000806880830895CF93DF93482F50E0CA0161 +:1021B000845C9A4FFC013491425E5A4FFA0184913B +:1021C000882369F190E0880F991FFC01EC50FB4FC8 +:1021D000A591B491FC01EE5FFA4FC591D4916623AD +:1021E00051F42FB7F8948C91932F909589238C9369 +:1021F000888189230BC0623061F42FB7F8948C91E9 +:10220000932F909589238C938881832B88832FBF6C +:1022100006C09FB7F8948C91832B8C939FBFDF915E +:10222000CF910895883071F1893068F4823031F1AE +:10223000833020F4813009F042C01DC0833089F022 +:102240008430E9F512C08B3059F18C3028F4893094 +:10225000E9F08A30A1F51EC08C3031F18E3079F56D +:1022600029C0809180008F7703C0809180008F7D8E +:1022700080938000089584B58F7702C084B58F7DE8 +:1022800084BD0895809190008F7707C08091900061 +:102290008F7D03C080919000877F80939000089588 +:1022A0008091C0008F7703C08091C0008F7D8093A4 +:1022B000C00008958091C200877F8093C200089576 +:1022C000FF920F931F93F62E482F50E0CA01865AB3 +:1022D0009A4FFC012491CA01845C9A4FFC0114912D +:1022E000425E5A4FFA0104910023C9F0222319F0EB +:1022F000822F0E941211E02FF0E0EE0FFF1FEE5F21 +:10230000FA4FA591B4919FB7F894FF2021F48C91D6 +:102310001095812302C08C91812B8C939FBF1F91BC +:102320000F91FF9008950F931F93482F50E0CA011B +:10233000865A9A4FFC012491CA01845C9A4FFC0191 +:102340000491425E5A4FFA011491112319F420E0CE +:1023500030E015C0222319F0822F0E941211812F24 +:1023600090E0880F991F805F9A4FFC01A591B4916E +:102370008C9120E030E0802311F021E030E0C901B1 +:102380001F910F91089520918F04309190048091B6 +:10239000910490919204281B390B2F733070C9015E +:1023A000089520918F043091900480919104909130 +:1023B00092042817390719F42FEF3FEF09C0E09175 +:1023C0009104F0919204E15BFB4F8081282F30E073 +:1023D000C901089520918F04309190048091910457 +:1023E000909192042817390719F42FEF3FEF13C08B +:1023F000E0919104F0919204E15BFB4F2081809188 +:1024000091049091920401968F739070909392042E +:102410008093910430E0C9010895109296041092BF +:10242000950488EE93E0A0E0B0E080939704909349 +:102430009804A0939904B0939A0485E092E0909355 +:1024400094048093930408950F931F93DF93CF9385 +:102450000F92CDB7DEB78C0169838091FE0188238E +:1024600069F083E0BE016F5F7F4F41E050E00E9462 +:10247000BB151816190614F49C0107C081E090E002 +:10248000F8019383828320E030E0C9010F90CF915F +:10249000DF911F910F91089583E00E949015089598 +:1024A000CF93DF9312C082E00E941B152FEF8F3F66 +:1024B0009207C9F0E0918F04F0919004E15BFB4F2B +:1024C0008083D0939004C0938F04C0918F04D091E7 +:1024D00090042196CF73D0708091910490919204D2 +:1024E000C817D90701F7DF91CF910895FC018081CA +:1024F0008E5F808380E864E875E042E450E00E94EB +:1025000034150895FC0181819081913A59F481320A +:1025100009F04CC080E067EF71E047E050E00E94B6 +:10252000341542C0913209F041C0803239F487EF4E +:1025300091E067E070E00E94781536C0823209F0C1 +:1025400035C082818093FE018091F7019091F8015E +:10255000A091F901B091FA01805B9440A040B04095 +:1025600019F58091FE0180FD12C087E797E79093EF +:102570000108809300082BE088E190E00FB6F89402 +:10258000A895809360000FBE209360000DC088E185 +:102590000FB6F89480936000109260000FBEA8956B +:1025A000109201081092000881E0089580E00895DB +:1025B000CF93DF930E947D1089EA94E00E949B15DF +:1025C00089B5806189BD09B400FEFDCF0E94F30387 +:1025D000C0E0D0E00E94D5032097E1F30E94000004 +:1025E000F9CFCF92DF92EF92FF920F931F93CF9389 +:1025F000DF937C016B018A01C0E0D0E00FC0D601FF +:102600006D916D01D701ED91FC910190F081E02D6C +:10261000C7010995C80FD91F0150104001151105B8 +:1026200071F7CE01DF91CF911F910F91FF90EF9045 +:10263000DF90CF900895EF92FF920F931F93CF9367 +:10264000DF937C018B01C0E0D0E0F8010F5F1F4FEA +:102650006491662359F0D701ED91FC910190F081CE +:10266000E02DC7010995C80FD91FEFCFCE01DF912B +:10267000CF911F910F91FF90EF900895EF92FF92ED +:102680000F931F938C01DC01ED91FC910190F0817F +:10269000E02D6DE009957C01D801ED91FC91019050 +:1026A000F081E02DC8016AE009959C012E0D3F1DC7 +:1026B000C9011F910F91FF90EF900895EF92FF9243 +:1026C0000F931F937C010E941B138C01C7010E9472 +:1026D0003E139C01200F311FC9011F910F91FF90E4 +:1026E000EF900895CF93DF93EC016115710519F414 +:1026F00020E030E00FC0DB010D900020E9F71197DA +:10270000A61BB70BE881F9810280F381E02DAD01B2 +:1027100009959C01C901DF91CF9108954F925F9275 +:102720007F928F929F92AF92BF92CF92DF92EF9261 +:10273000FF920F931F93DF93CF93CDB7DEB7A1978F +:102740000FB6F894DEBF0FBECDBF2C01742ECB01A7 +:10275000223008F42AE019A231E2C32ED12CCC0E8B +:10276000DD1E822E9924AA24BB24672D752FA50176 +:1027700094010E94921979018A01C801B701A5014B +:1027800094010E947319472D461B0894C108D10873 +:102790004A3014F4405D01C0495CF6014083E11405 +:1027A000F1040105110521F07E2C5F2DC801DDCF5C +:1027B000C201B6010E947213A1960FB6F894DEBF53 +:1027C0000FBECDBFCF91DF911F910F91FF90EF9082 +:1027D000DF90CF90BF90AF909F908F907F905F9051 +:1027E0004F900895DC012115310541F4ED91FC91E4 +:1027F0000190F081E02D642F099508950E948E13B9 +:102800000895EF92FF920F931F939A017B0100E0CE +:1028100010E0B801A7010E94F2131F910F91FF90E1 +:10282000EF900895CF92DF92EF92FF920F931F9354 +:102830006C017B019A0100E010E0B801A7010E9441 +:10284000F2138C01C6010E943E13080F191FC80124 +:102850001F910F91FF90EF90DF90CF900895EF922E +:10286000FF920F931F939A01E62EFF2400E010E0E1 +:10287000B801A7010E94F2131F910F91FF90EF90F2 +:102880000895CF92DF92EF92FF920F931F936C0106 +:10289000E62E9A01FF2400E010E0B801A7010E9493 +:1028A000F2138C01C6010E943E13080F191FC801C4 +:1028B0001F910F91FF90EF90DF90CF900895CF92EE +:1028C000DF92EF92FF920F931F93CF93DF93EC0170 +:1028D0006A017B012115310541F4E881F9810190FC +:1028E000F081E02D642F09951FC02A303105D1F405 +:1028F00077FF17C0E881F9810190F081E02D6DE24A +:1029000009958C0144275527BA014C195D096E09B8 +:102910007F09CE012AE00E948E139801280F391FEB +:1029200004C02AE00E948E139C01C901DF91CF915F +:102930001F910F91FF90EF90DF90CF900895EF924D +:10294000FF920F931F937B019A010027F7FC0095DC +:10295000102FB801A7010E945F141F910F91FF90E3 +:10296000EF900895CF92DF92EF92FF920F931F9313 +:102970006C017B019A010027F7FC0095102FB8012C +:10298000A7010E945F148C01C6010E943E13080F2C +:10299000191FC8011F910F91FF90EF90DF90CF900A +:1029A00008950E9472130895EF92FF920F931F9360 +:1029B0007C010E9472138C01C7010E943E13080F14 +:1029C000191FC8011F910F91FF90EF900895282FB4 +:1029D0008091A3048823C1F057FF1AC015C0289A1C +:1029E0009093A2048091F1008193E217F307B9F765 +:1029F0004115510539F08091F200882319F48BE6D6 +:102A00008093E800AFBF02C04FEF5FEFCA010895A7 +:102A1000AFB7F89427702093E9008091F200282F37 +:102A200030E0241735070CF4A901FB019B01240FAA +:102A3000311D94E6DACFDF93CF930F92CDB7DEB797 +:102A4000BE016F5F7F4F41E050E00E94E7140197A5 +:102A500019F02FEF3FEF03C08981282F30E0C90123 +:102A60000F90CF91DF910895FF920F931F93F82E4F +:102A7000142F052F4091A6045091A704212F302F29 +:102A8000C901DC01FB016EEF29C0F7FE02C0949181 +:102A900001C090812091A4043091A504241735072A +:102AA000ACF48091E8008570E1F38091E80082FF4A +:102AB00003C02FEF3FEF17C09093F100C9010196BB +:102AC0008F739070892B11F46093E8002F5F3F4F54 +:102AD0003093A5042093A404119731961097A9F67A +:102AE000812F902F9C01C9011F910F91FF90089594 +:102AF0009C018091E80082FFFCCFF901260F311D77 +:102B000003C08091F1008193E217F307D1F7289A6F +:102B100084E68093A2048BEF8093E800CB010895B4 +:102B20008093E9008091F200882319F08AE3809372 +:102B3000E800089508951092A30481E08093D700DF +:102B400080EA8093D80082E089BD09B400FEFDCF01 +:102B500061E070E080E090E00E94241080E98093C2 +:102B6000D8008CE08093E2001092E000559A209A01 +:102B70005D98289808955F926F927F928F929F92AE +:102B8000AF92BF92CF92DF92EF92FF920F931F937B +:102B9000CF93DF93E82E842E752E8091A304882393 +:102BA00071F18B01242F352FC901EC017AEFF72E3B +:102BB00067E0962E9E2050E4552E8E2D90E040E248 +:102BC000A42EB12CA822B9223AE3632E20E4C22E0F +:102BD000D12CC822D92258C09FB7F8949092E9000E +:102BE0008091E80085FD02C020E004C08091F200E1 +:102BF000252D281B9FBF222361F4FA9419F42FEF8F +:102C00003FEF4DC061E070E080E090E00E94241052 +:102C10003BC0822F90E0C817D9070CF42C2FC21BA1 +:102C2000D1094FB7F8949092E900A114B10421F4AE +:102C300006C01092F10021502223D9F719C0E7FCF9 +:102C400003C0F801922F10C0C801322F06C0FC014A +:102C50000196E491E093F10031503323C1F706C0AF +:102C600081918093F10091509923D1F7020F111DAA +:102C70008091E80085FF05C0209729F4C114D10494 +:102C800011F06092E8004FBF209709F0A5CF5D9A40 +:102C900084E68093A104282D372DC9019C01C90128 +:102CA000DF91CF911F910F91FF90EF90DF90CF9028 +:102CB000BF90AF909F908F907F906F905F9008959E +:102CC0001F920F920FB60F9211242F933F934F93A1 +:102CD0005F936F937F938F939F93AF93BF93EF9384 +:102CE000FF938091E1001092E100982F83FF0FC0C5 +:102CF0001092E90081E08093EB001092EC0082E3F7 +:102D00008093ED001092A30488E08093F00092FF7E +:102D100034C083E08093E9008091F200882319F0A9 +:102D20008AE38093E8008FB7F89492E09093E900EB +:102D30009091F2008FBF992321F083E994E00E94E3 +:102D400050128091A104882351F08091A1048150F8 +:102D50008093A1048091A104882309F45D98809157 +:102D6000A204882351F08091A20481508093A20490 +:102D70008091A204882309F42898FF91EF91BF91D4 +:102D8000AF919F918F917F916F915F914F913F9103 +:102D90002F910F900FBE0F901F9018950F931F93B8 +:102DA000DF93CF930F92CDB7DEB719828E010F5FFD +:102DB0001F4FC8010E947612C8010E9467198981BD +:102DC00090E00F90CF91DF911F910F9108951F9286 +:102DD0000F920FB60F921124EF92FF921F932F9331 +:102DE0003F934F935F936F937F938F939F93AF9393 +:102DF000BF93EF93FF93DF93CF93CDB7DEB7619788 +:102E0000DEBFCDBF1092E9008091E80083FF0FC1C3 +:102E1000FE0131969E01275F3F4F03C08091F10074 +:102E20008193E217F307D1F7289A84E68093A204EE +:102E300082EF8093E800998197FF05C08091E800B8 +:102E400080FFFCCF03C08EEF8093E800292F30E095 +:102E5000C90180769070892B09F0C2C08A818823CD +:102E600029F41092F1001092F100D6C0813009F4DB +:102E7000D3C0833009F4D0C0853049F48091E80094 +:102E800080FFFCCF8B8180688093E300C5C08630D3 +:102E900009F07CC01C81EF80F8841230C1F51092DB +:102EA000E9001092A5041092A4041092A7041092B5 +:102EB000A6040E94CE1699E0FE013996DF01292F63 +:102EC0001D922A95E9F799871A8791E09E8790E8E5 +:102ED000988B9AEF998B2091A4043091A504275FD9 +:102EE0003F4F3C872B878D871092E9001092A504F5 +:102EF0001092A404F092A704E092A60480E0BF011F +:102F000049E050E00E9434150E94CE1685C0109210 +:102F1000E9001092A5041092A404F092A704E09294 +:102F2000A604123241F482E290E00E945F19892BDC +:102F300009F476C071C0113079F488E0E816F10424 +:102F400019F481E08093A8048091A804882309F0F3 +:102F50006BC0E4E0F6E013C0133009F061C08B8170 +:102F6000882319F4E6ECF5E00AC0823019F4EAECA3 +:102F7000F5E005C0813009F053C0ECEEF5E0449176 +:102F800080E8BF0150E00E94341546C0873009F444 +:102F900047C0883021F481E08093F1003DC0893042 +:102FA000D9F523703070232BD9F5E9E2F6E091E0F2 +:102FB00031E026E39093E9003093EB008491809315 +:102FC000EC002093ED009F5F3196953099F78EE7E6 +:102FD0008093EA001092EA008B818093A3041CC0C6 +:102FE0008F8198851092E9001092A5041092A40494 +:102FF0009093A7048093A6048D81882329F4CE01A1 +:1030000001960E94821206C0823051F4CE010196D0 +:103010000E943018882321F08EEF8093E80007C0CB +:1030200081E28093EB0003C0E6E1F6E0A8CF619671 +:10303000DEBFCDBFCF91DF91FF91EF91BF91AF91F7 +:103040009F918F917F916F915F914F913F912F91C0 +:103050001F91FF90EF900F900FBE0F901F9018954B +:10306000FC0191818081813A31F4913089F080E0D6 +:10307000933089F40DC0813269F49B3021F4828150 +:103080008093FF0105C09A3029F482818093000269 +:1030900081E0089580E00895EF92FF920F931F93CF +:1030A0008C01E62EDC01ED91FC910480F581E02D90 +:1030B0000995F82ED801ED91FC910680F781E02D5D +:1030C000C8016E2D09958F2D90E01F910F91FF90F3 +:1030D000EF9008951092AA041092AE041092AD04DD +:1030E00087E192E09093AC048093AB040895EF9253 +:1030F000FF920F931F93DF93CF930F92CDB7DEB75D +:1031000089838B017A0184E0BE016F5F7F4F41E0CC +:1031100050E00E94BB1584E4B801A7010E94BB15D2 +:103120000F90CF91DF911F910F91FF90EF90089535 +:1031300082E048E050E00E9477180895FC01168272 +:103140001782108611861286138614823496BF0168 +:103150000E9498180895DC01683810F0685829C05A +:10316000E62FF0E067FF13C0E058F04081E090E008 +:1031700002C0880F991FEA95E2F7809514962C916A +:103180001497282314962C93149760E012C0E555E9 +:10319000F94F6491662319F420E030E01DC067FF09 +:1031A00008C014968C9114978D7F14968C93149765 +:1031B0006F77FD0190E0662321F08681861709F480 +:1031C00016829F5F31969630B1F7CD011496BD01FE +:1031D0000E94981821E030E0C9010895CF93DF9351 +:1031E000DC01683810F0685825C0E62FF0E067FF72 +:1031F00012C0E058F04081E090E002C0880F991FB3 +:10320000EA95E2F714962C911497282B14962C9398 +:10321000149760E00FC0E555F94F64916623D9F12A +:1032200067FF08C014968C911497826014968C9353 +:1032300014976F7716968C9116978617A9F11796A3 +:103240008C911797861781F118968C91189786178D +:1032500059F119968C911997861731F11A968C911C +:103260001A97861709F11B968C911B978617E1F028 +:10327000ED01E0E0F0E09E2F8E81882321F4EA0F3B +:10328000FB1F668306C09F5F31962196E630F105ED +:1032900091F7963049F481E090E013969C938E93D9 +:1032A000129720E030E007C0CD011496BD010E94C6 +:1032B000981821E030E0C901DF91CF91089580E8AE +:1032C0006DE276E045E650E00E9434150895FC0179 +:1032D00080818F5F808380E862E976E049E150E099 +:1032E0000E9434150895629FD001739FF001829F60 +:1032F000E00DF11D649FE00DF11D929FF00D839F85 +:10330000F00D749FF00D659FF00D9927729FB00D21 +:10331000E11DF91F639FB00DE11DF91FBD01CF0134 +:1033200011240895A1E21A2EAA1BBB1BFD010DC09A +:10333000AA1FBB1FEE1FFF1FA217B307E407F50765 +:1033400020F0A21BB30BE40BF50B661F771F881F41 +:10335000991F1A9469F760957095809590959B01D7 +:10336000AC01BD01CF010895EE0FFF1F0590F49150 +:08337000E02D0994F894FFCF51 +:10337800433A5C55736572735C64656C6C5C446F4E +:1033880063756D656E74735C41726475696E6F5CAC +:103398006C69627261726965735C424C455C616319 +:1033A800695F71756575652E63707000203A00431A +:1033B800002045004143495F4556545F444154410C +:1033C8005F43524544495420202020200044617422 +:1033D800612043726564697420617661696C616219 +:1033E8006C653A200064617461207472616E736D5B +:1033F8006D697420737563636573732120204C6550 +:103408006E6774683A20002020202000646174618F +:10341800207472616E736D6D6974206661696C20C9 +:103428002100746865206E6577206E616D6520697E +:103438007320746F6F206C6F6E67004552524F5245 +:1034480020003A20000A000607426C656E644D6948 +:1034580063726F00F903F903018000010400010899 +:103468000001020001800000E100000000000001EE +:1034780001000000002412F112C311EA11D1114C0D +:10348800125012000000004C18F112EE18AB189EF2 +:0234980018001A +:00000001FF diff --git a/Jump2DFU/Jump2DFU.ino b/Jump2DFU/Jump2DFU.ino new file mode 100644 index 0000000..b8554ed --- /dev/null +++ b/Jump2DFU/Jump2DFU.ino @@ -0,0 +1,26 @@ + +#include +#include +#include +#include + +void setup() +{ + ble_begin(); +} + +void loop() +{ + if ( ble_available() ) + { + if(0xFF == ble_read()) + { + *(uint16_t *)0x0800 = 0x7777; + wdt_enable(WDTO_15MS); + while(1); + } + } + + ble_do_events(); +} + diff --git a/README.md b/README.md index dc82a00..498ba40 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,34 @@ -dfu-ota-for-blend -================= +# dfu-ota-for-blend/blend micro # +--- DFU OTA for Blend and Blend Micro boards. + +## Introduction ## +--- + +In the "Source" folder, it contains the source code and makefile to generate the hex file of bootloader. To compile the source code correctly, you need to change the folder name from "ble-caterina" to "caterina" and put it into the folder "Arduino\hardware\arduino\bootloaders". So you'd better backup the previous folder of "caterina" fisrt. + +In the "Release" folder, it contains a hex file of bootloader we have generated for only Blend Micro. + +In the "Jump2DFU" folder, it contains a sketch and the corresponding hex file running on Blend Micro. The sketch is used to jump to bootloader when Blend Micro received 0xFF from app. The sketch relys on our BLE libraries. + +## Getting Started ## +--- + +1. Copy the released hex file, Caterina-BlendMicro.hex, to "Arduino\hardware\blend\bootloaders\caterina" if you have added our Blend/Blend Micro boards onto Arduino. You'd better backup the previous hex file of Blend Micro. + +2. You need an Arduino board with Arduino ISP sketch programmed. Connect Blend Micro with the Arduino board. More info about Arduino ISP, please refer [here](http://arduino.cc/en/Tutorial/ArduinoISP). + +3. Open Arduino IDE, select the target board:**Tools->Board->Blend Micro 3.3v/8MHz** and then burn the bootloader:**Tools->Burn Bootloader**. After burnt the bootloader, disconnect Blend Micro from the Arduino and power Blend Micro with micro USB or the VIN. + +4. Download the nRF Toolbox app on the App Store. Here use ipod for example. + +5. Download the "Jump2DFU.hex" via Dropbox, Gmail, QQ or any other app that can store the hex file. + +6. Select the downloaded hex file and open it with nRF Toolbox. Click on the "SELECT DEVICE" button to select the device with DFU ability. Then click "Upload". + +7. After uploading, the sketch will run. Use the LightBlue app to send 0xFF to Blend Micro, it will jump to the DFU bootloader. + +8. You can download any other sketchs as Jump2DFU by nRF Toolbox. Just complie the sketch running on Blend Micro to generate the hex file and then follow step 5 and step 6. + +9. You can also jump to the DFU bootloader by pressing the on board reset button so that you can select the device on step 6. \ No newline at end of file diff --git a/Release/Caterina-BlendMicro.hex b/Release/Caterina-BlendMicro.hex new file mode 100644 index 0000000..5ce09ea --- /dev/null +++ b/Release/Caterina-BlendMicro.hex @@ -0,0 +1,258 @@ +:10700000C0C10000D9C10000D7C10000D5C1000037 +:10701000D3C10000D1C10000CFC10000CDC100002C +:10702000CBC10000C9C10000C7C10000C5C100003C +:10703000C3C10000C1C10000BFC10000BDC100004C +:10704000BBC100001AC20000B7C10000B5C10000FA +:10705000B3C10000B1C10000AFC10000ADC100006C +:10706000ABC10000A9C10000A7C10000A5C100007C +:10707000A3C10000A1C100009FC100009DC100008C +:107080009BC1000099C1000097C1000095C100009C +:1070900093C1000091C100008FC100008DC10000AC +:1070A0008BC1000089C1000087C1000000070600F5 +:1070B0000003024207000000000000000000000082 +:1070C00000000000000000000000000000001F069B +:1070D0001000000000000000030004010100000691 +:1070E0000000D00000000000000000000015001F9C +:1070F00006101C300200000000000000000000002C +:107100000000000000001000000014039001FF00C8 +:107110001F061038FFFF02580A050000000000009B +:10712000000000000010000000000000000000004F +:1071300000050610540000000000000000000000E0 +:10714000000000000000000000000000000000003F +:1071500000001F06200004040202000128000100B4 +:1071600018040405050002280301020300002A0494 +:107170000414001F06201C0300032A000144465586 +:1071800064696373656D692E636F6D0000000000B4 +:10719000000404001F06203805050004280301022E +:1071A0000500012A0604030200052A0101800004EB +:1071B00004050500001F06205406280301020700ED +:1071C000042A0604090800072A04010A0012000024 +:1071D000000A000404001F062070020200082800B4 +:1071E000010118040405050009280301220A00050D +:1071F0002A2604050400001F06208C0A2A05010027 +:1072000000000046140302000B29020100000404E0 +:107210001010000C280001001F0620A823D1BCEA92 +:107220005F782315DEEF12123015000004041313EB +:10723000000D280301040E00001F0620C423D1BC4A +:10724000EA5F782315DEEF121232150000441014A5 +:1072500000000E153202000000001F0620E00000B2 +:10726000000000000000000000000000000000041A +:10727000041313000F2803011810001F0620FC0040 +:1072800023D1BCEA5F782315DEEF1212311500001E +:107290005410140000101531020000001F062118C0 +:1072A00000000000000000000000000000000000DE +:1072B0000000461403020011290201000005062106 +:1072C000340000000000000000000000000000008A +:1072D00000000000000000000000000000001F0689 +:1072E00040002A0501000404000A000B15320200C8 +:1072F0000804000E0000153102040204001000050D +:1073000006401C001100000000000000000000000A +:10731000000000000000000000000000000000006D +:107320001306500023D1BCEA5F782315DEEF12125A +:10733000000000000000000000000000000000004D +:10734000000C0660000000000000000000000000CB +:10735000000000000000000000000000000000002D +:1073600000000606F0000377240000000000000083 +:10737000000000000000000000000000000000000D +:10738000000011241FBECFEFDAE0DEBFCDBF11E059 +:10739000A0E0B1E0E6EDFFE702C005900D92AA3152 +:1073A000B107D9F712E0AAE1B1E001C01D92A832FD +:1073B000B107E1F721D10DC623CEFB01DC0102C0EC +:1073C00005900D9241505040D8F70895FB01DC0123 +:1073D00002C001900D9241505040D8F70895E1E667 +:1073E000F0E080E8808381E08083F89410926F0061 +:1073F00010928100109285001092840085BF15BE06 +:1074000047980C94000008952091050230910602DF +:107410002E5F3F4F3093060220930502932F37FFD4 +:1074200003C08EEF831B982F990F921710F4479883 +:107430000895479A089520E881E090E00FB6F89407 +:1074400020936100809361000FBE81E085BF92E0D0 +:1074500095BF3F9A209A559AE1E6F0E02083808319 +:107460005D9A289A109289008AEF80938800909301 +:107470006F0083E08093810008951F920F920FB6F2 +:107480000F9211242F938F939F93EF93FF9310925A +:10749000850010928400E0E0F0E0859194918F5F88 +:1074A0009F4F49F080911E0190911F01019690938A +:1074B0001F0180931E01FF91EF919F918F912F915A +:1074C0000F900FBE0F901F9018950F931F93DF938F +:1074D000CF93CDB7DEB7A2970FB6F894DEBF0FBE3D +:1074E000CDBF8C0181E291E0BE016F5F7F4F27D25B +:1074F000882309F476C08B81853879F1863848F481 +:10750000833809F45AC0843800F5813809F05EC028 +:107510000EC08A3849F18B3820F4863809F056C0FD +:107520004CC08C38B9F18D3809F050C028C08E811C +:10753000809334018C81823021F481E0809320019A +:1075400045C0833009F042C038C08C818E3009F0CC +:107550003DC08D818823D1F530C010921F0110925B +:107560001E018091340108C010921F0110921E016B +:107570008C8190913601890F8093360127C010923B +:107580001F0110921E018D81823901F18091360117 +:107590008F5FF2CF10921F0110921E019C81F801A3 +:1075A0008081981719F08281981781F481E291E027 +:1075B000BE016E5F7F4F3DD309C0609105017091A0 +:1075C000060180910301909104015FD28091200116 +:1075D000882339F081E291E0AFD0882311F4109232 +:1075E0002001A2960FB6F894DEBF0FBECDBFCF919B +:1075F000DF911F910F91089540910008509101086B +:10760000109201081092000884B714BE28E10FB64A +:10761000F89420936000109260000FBE90E0FC018F +:10762000E270F07081FD0DC0859194918F5F9F4F46 +:1076300041F080910801909109014817590709F01C +:10764000CEDEF9DE789484E080932F018CEA90E717 +:10765000909331018093300186E18093320181E281 +:1076600091E04BD280E091E0A8D40DC080911E0142 +:1076700090911F0181549F4110F01092070180E00A +:1076800091E023DFC1DE80910701882379F7A7DE2F +:1076900080E090E00895AF92BF92CF92DF92EF9298 +:1076A000FF920F931F93DF93CF93CDB7DEB7A197D0 +:1076B0000FB6F894DEBF0FBECDBF7C018B01DD2479 +:1076C00081E2C82E5E010894A11CB11C1DC0D70127 +:1076D0001F96ED91FC9150979C9DC0011124E80FDD +:1076E000F91F31964491319750E04E5F5F4FC501CD +:1076F000BF0163DEC50105D1882361F0F8018081F7 +:107700008F5F8083DD24D394D8019C91F701818918 +:107710009817E8F28D2DA1960FB6F894DEBF0FBE34 +:10772000CDBFCF91DF911F910F91FF90EF90DF9030 +:10773000CF90BF90AF900895BF92CF92DF92EF921B +:10774000FF920F931F93DF93CF93CDB7DEB7A3972D +:107750000FB6F894DEBF0FBECDBF7C0119828E013B +:107760000F5F1F4FB80197DF92E0C92ED12CCC0ECE +:10777000DD1EB02E012FC601E0D08823E1F38E81FB +:10778000813021F0823051F084E009C0C7016B2DB7 +:10779000702F81DFC701B601D2D0EDCF80E0A39674 +:1077A0000FB6F894DEBF0FBECDBFCF91DF911F9112 +:1077B0000F91FF90EF90DF90CF90BF9008951092BF +:1077C0004E0110924F016E98769A84B1866084B90A +:1077D000579A5F9A2398209A8CB581678CBD08953B +:1077E0008CB1829586958695837080958170089579 +:1077F000F7DF90914E01882329F4992309F448C0BA +:107800005F980895992321F410925001109251012C +:107810005F98509151015EBD0DB407FEFDCF8EB54E +:1078200080930702809152018EBD0DB407FEFDCFFB +:107830004EB540930802552349F0252F30E0842FA0 +:1078400090E08217930714F4452F4150842F403263 +:1078500008F08FE1A9E0B2E0E3E5F1E0282F30E0A5 +:107860002A0F3B1F08C080818EBD0DB407FEFDCFDF +:107870008EB58D933196A217B307A9F75F9A109230 +:107880004E0180910802882319F081E080934F0116 +:1078900008950F931F93182F092FAADF80914F018E +:1078A000882371F0812F902F9C01D901E7E0F2E04D +:1078B00081E201900D928150E1F710924F0181E039 +:1078C0001F910F9108950F931F93182F092F8091E7 +:1078D0004F01882309F48CDF80914F01882371F0D8 +:1078E000812F902F9C01D901E7E0F2E081E2019025 +:1078F0000D928150E1F710924F0181E01F910F919D +:107900000895FC0121812032B0F480914E0188233A +:1079100091F41092500161E571E030E02F5F3F4F2C +:10792000AF014F5F5F4FCB01BA01A9014FDD81E08D +:1079300080934E01089580E00895ABCF08950F9392 +:107940001F93CF93DF938C01EB01CB01BCDF282F7A +:107950008823A9F18A81883829F0893819F1863875 +:1079600071F512C0DE01F8017C9690E013968C91BF +:10797000139780831B968C911B9780879F5F11962E +:107980003196983099F71BC0F8017C9680E0108200 +:1079900010868F5F31968830D1F7F80114A683895D +:1079A000858B0DC08B819C81F801978B868B8D8197 +:1079B0009E81918F808F8F819885938F828F822F68 +:1079C000DF91CF911F910F910895EF92FF921F9336 +:1079D000DF93CF93CDB7DEB7E6970FB6F894DEBF4F +:1079E0000FBECDBF142F898382E0E82EF12CEC0E60 +:1079F000FD1EC70150E0EADC1E5F1F8B125085E1BF +:107A0000888F8981898F9E01265E3F4FC901B7010A +:107A1000412F50E0DBDCCE01469673DFE6960FB6D1 +:107A2000F894DEBF0FBECDBFCF91DF911F91FF90C5 +:107A3000EF9008950F931F93DF93CF93CDB7DEB7E9 +:107A4000A1970FB6F894DEBF0FBECDBF8C0182E0C8 +:107A50008A8381E18B836C83CE01019652DF882378 +:107A600049F0F8017C9690E0108210869F5F319675 +:107A70009830D1F7A1960FB6F894DEBF0FBECDBFF8 +:107A8000CF91DF911F910F910895DF93CF93CDB7E1 +:107A9000DEB7A1970FB6F894DEBF0FBECDBF25E0CD +:107AA0002A832FE02B839D838C837F836E83CE017B +:107AB000019627DFA1960FB6F894DEBF0FBECDBFAB +:107AC000CF91DF910895DF93CF93CDB7DEB7A19724 +:107AD0000FB6F894DEBF0FBECDBF81E08A838EE083 +:107AE0008B83CE0101960DDFA1960FB6F894DEBF11 +:107AF0000FBECDBFCF91DF910895EF92FF920F930C +:107B00001F93DF93CF93CDB7DEB7C354D0400FB6EA +:107B1000F894DEBF0FBECDBF8C01FC017C9680E0E7 +:107B2000108210868F5F31968830D1F748DEC80109 +:107B3000CADF92E2E92EF12CEC0EFD1EC801B7015E +:107B4000FEDE8823D9F38CA18438C1F7198284E042 +:107B50008A8381E88B8382E08C831D828E83A7E0F9 +:107B6000B2E0FE01319681E201900D928150E1F781 +:107B700081E080934F01CD5BDF4F0FB6F894DEBFFD +:107B80000FBECDBFCF91DF911F910F91FF90EF906E +:107B90000895CF93DF93EC01DB0110926F0083E037 +:107BA000FE0180935700E89507B600FCFDCF40E04A +:107BB00050E061E08C9111963C91119720E0F90121 +:107BC000E80FF11DCF011296FA01EC0FFD1F0C0119 +:107BD00060935700E89511244E5F5F4F4038510580 +:107BE00049F785E0FE0180935700E89507B600FC51 +:107BF000FDCF81E180935700E89582E080936F008C +:107C0000DF91CF9108959C01462F80910302B90125 +:107C1000DCDE282F882339F0E0917101F0917201A8 +:107C200085898150858B8BB190E289278BB9822F12 +:107C30000895DF92EF92FF920F931F93DF93CF93FC +:107C4000CDB7DEB7A8970FB6F894DEBF0FBECDBF95 +:107C5000AC018B0185B191E0892785B95093720100 +:107C600040937101FB019281809102029817F1F01B +:107C700080910402981709F092C18381853009F43C +:107C80005FC1863050F4833009F423C1843008F09A +:107C90002AC1823009F083C115C1883009F470C14E +:107CA000843121F0863009F07AC161C180910C01E4 +:107CB000833009F464C0843009F468C0813009F06D +:107CC0006EC120910302322F377081E090E001C035 +:107CD000880F3A95EAF7269526952695FA01E20F40 +:107CE000F11D248D282B248F809524A1822384A329 +:107CF000F801268130E040E050E0522F442733273E +:107D00002227858190E0A0E0B0E0DC019927882758 +:107D1000282B392B4A2B5B2B838190E0A0E0B0E02D +:107D2000282B392B4A2B5B2B848190E0A0E0B0E01C +:107D3000BA2FA92F982F8827282B392B4A2B5B2B5A +:107D40002093730130937401409375015093760131 +:107D5000215030404040504020503047404050403B +:107D600020F084E080930F0103C082E080930C0137 +:107D70008DE091E063E047DF8823D1F310C180E11B +:107D800091E063E040DF8823D1F309C1F801D0809E +:107D9000FEEFDF0E2091770130917801211531053A +:107DA00091F18091790190917A01019790937A01F4 +:107DB00080937901892B39F530937A0120937901E9 +:107DC00020917B0130917C0140917D0150917E0199 +:107DD00081E189831A822B83BB27A52F942F832FC0 +:107DE0008C83CA01AA27BB278D83252F33274427DD +:107DF00055272E837E010894E11CF11CC70166E023 +:107E000002DF8823D9F3FF2425C090910102E92FD6 +:107E1000F0E0EF57FE4FD801AF0DB11D13968C91D6 +:107E200080839F5F90930102903899F41092010231 +:107E300080917F019091800161E871E0AADE8091DC +:107E40007F019091800180589F4F90938001809393 +:107E50007F01F394FD14C8F280917B0190917C0125 +:107E6000A0917D01B0917E018D0D911DA11DB11DCF +:107E700080937B0190937C01A0937D01B0937E0160 +:107E800020917301309174014091750150917601F8 +:107E9000281739074A075B0709F081C080917F01E5 +:107EA0009091800101969093800180937F010197CA +:107EB00061E871E06EDE83E191E063E0A4DE882397 +:107EC000D1F36DC080910C01823009F068C083E06D +:107ED00007C080910C018250823008F060C084E0BD +:107EE00080930C015CC080910C01843009F057C074 +:107EF000DE011196E6E1F1E083E001900D92815000 +:107F0000E1F720917B0130917C0140917D015091FE +:107F10007E018091730190917401A0917501B091DF +:107F20007601281739074A075B0741F48E010F5F76 +:107F30001F4FC80163E067DE8823D9F385E0D0CF07 +:107F400080910C01853059F5CA0161E073DD8E0125 +:107F5000095F1F4F06C08091710190917201B801B5 +:107F6000EEDC89858638B9F71092070118C0809138 +:107F7000710190917201A7DD8823C9F381E0B0CF30 +:107F8000FB01358120E0848190E0822B932B90933C +:107F900078018093770190937A0180937901A89674 +:107FA0000FB6F894DEBF0FBECDBFCF91DF911F910A +:107FB0000F91FF90EF90DF90089521E020930C0146 +:107FC000A2E0B2E0FC0183E001900D928150E1F764 +:067FD0000895F894FFCFB4 +:107FD600020304B40050000177770008FF10010186 +:0A7FE6001002011003011004010055 +:040000030000700089 +:00000001FF diff --git a/Source/ble-caterina/BLE/aci.h b/Source/ble-caterina/BLE/aci.h new file mode 100644 index 0000000..d024138 --- /dev/null +++ b/Source/ble-caterina/BLE/aci.h @@ -0,0 +1,666 @@ +/* Copyright (c) 2014, Nordic Semiconductor ASA + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/** + * @file + * + * @defgroup aci aci + * @{ + * @ingroup lib + * + * @brief Definitions for the ACI (Application Control Interface) + * @remarks + * + * Flow control from application mcu to nRF8001 + * + * Data flow control: + * The flow control is credit based and the credit is initally given using the "device started" event. + * A credit of more than 1 is given to the application mcu. + * These credits are used only after the "ACI Connected Event" is sent to the application mcu. + * + * every send_data that is used decrements the credit available by 1. This is to be tracked by the application mcu. + * When the credit available reaches 0, the application mcu shall not send any more send_data. + * Credit is returned using the "credit event", this returned credit can then be used to send more send_data. + * This flow control is not necessary and not available for Broadcast. + * The entire credit available with the external mcu expires when a "disconnected" event arrives. + * + * Command flow control: + * When a command is sent over the ACI, the next command shall not be sent until after a response + * for the command sent has arrived. + * + */ + +#ifndef ACI_H__ +#define ACI_H__ + +#include + +/** + * Define an _aci_packed_ macro we can use in structure and enumerated type + * declarations so that the types are sized consistently across different + * platforms. In particular Arduino platforms using the GCC compiler and the + * Nordic processors using the Keil compiler. + * + * It's really the GNU compiler platforms that need a special keyword to get + * tight packing of values. On GNU platforms we can use the keyword: + * __attribute__((__packed__)) + * The thing is that while this keyword does the right thing with old and new + * versions of the gcc (C) compiler it only works right with g++ (C++) compiler + * versions that are version 4 or newer. + */ +#ifdef __GNUC__ +# if __GNUC__ >= 4 +# define _aci_packed_ __attribute__((__packed__)) +# else +# error "older g++ versions don't handle packed attribute in typedefs" +# endif +#else +# define _aci_packed_ +#endif + +/* + * Define a macro that compares the size of the first parameter to the integer + * value of the second parameter. If they do not match, a compile time error + * for negative array size occurs (even gnu chokes on negative array size). + * + * This compare is done by creating a typedef for an array. No variables are + * created and no memory is consumed with this check. The created type is + * used for checking only and is not for use by any other code. The value + * of 10 in this macro is arbitrary, it just needs to be a value larger + * than one to result in a positive number for the array size. + */ +#define ACI_ASSERT_SIZE(x,y) typedef char x ## _assert_size_t[-1+10*(sizeof(x) == (y))] + +/** + * @def ACI_VERSION + * @brief Current ACI protocol version. 0 means a device that is not yet released. + * A numer greater than 0 refers to a specific ACI version documented and released. + * The ACI consists of the ACI commands, ACI events and error codes. + */ +#define ACI_VERSION (0x02) +/** + * @def BTLE_DEVICE_ADDRESS_SIZE + * @brief Size in bytes of a Bluetooth Address + */ +#define BTLE_DEVICE_ADDRESS_SIZE (6) +/** + * @def ACI_PACKET_MAX_LEN + * @brief Maximum length in bytes of a full ACI packet, including length prefix, opcode and payload + */ +#define ACI_PACKET_MAX_LEN (32) +/** + * @def ACI_ECHO_DATA_MAX_LEN + * @brief Maximum length in bytes of the echo data portion + */ +#define ACI_ECHO_DATA_MAX_LEN (ACI_PACKET_MAX_LEN - 3) +/** + * @def ACI_DEVICE_MAX_PIPES + * @brief Maximum number of ACI pipes + */ +#define ACI_DEVICE_MAX_PIPES (62) +/** + * @def ACI_PIPE_TX_DATA_MAX_LEN + * @brief Maximum length in bytes of a transmission data pipe packet + */ +#define ACI_PIPE_TX_DATA_MAX_LEN (20) +/** + * @def ACI_PIPE_RX_DATA_MAX_LEN + * @brief Maximum length in bytes of a reception data pipe packet + */ +#define ACI_PIPE_RX_DATA_MAX_LEN (22) +/** + * @def ACI_GAP_DEVNAME_MAX_LEN + * @brief Maximum length in bytes of the GAP device name + */ +#define ACI_GAP_DEVNAME_MAX_LEN (20) +/** + * @def ACI_AD_PACKET_MAX_LEN + * @brief Maximum length in bytes of an AD packet + */ +#define ACI_AD_PACKET_MAX_LEN (31) +/** + * @def ACI_AD_PACKET_MAX_USER_LEN + * @brief Maximum usable length in bytes of an AD packet + */ +#define ACI_AD_PACKET_MAX_USER_LEN (31 - 3) +/** + * @def ACI_PIPE_INVALID + * @brief Invalid pipe number + */ +#define ACI_PIPE_INVALID (0xFF) + +/** + * @enum aci_pipe_store_t + * @brief Storage type identifiers: local and remote + */ +typedef enum +{ + ACI_STORE_INVALID = 0x0, + ACI_STORE_LOCAL= 0x01, + ACI_STORE_REMOTE= 0x02 +} _aci_packed_ aci_pipe_store_t; + +/** + * @enum aci_pipe_type_t + * @brief Pipe types + */ +typedef enum +{ + ACI_TX_BROADCAST = 0x0001, + ACI_TX = 0x0002, + ACI_TX_ACK = 0x0004, + ACI_RX = 0x0008, + ACI_RX_ACK = 0x0010, + ACI_TX_REQ = 0x0020, + ACI_RX_REQ = 0x0040, + ACI_SET = 0x0080, + ACI_TX_SIGN = 0x0100, + ACI_RX_SIGN = 0x0200, + ACI_RX_ACK_AUTO = 0x0400 +} _aci_packed_ aci_pipe_type_t; + +ACI_ASSERT_SIZE(aci_pipe_type_t, 2); + +/** + * @enum aci_bd_addr_type_t + * @brief Bluetooth Address types + */ +typedef enum +{ + ACI_BD_ADDR_TYPE_INVALID = 0x00, + ACI_BD_ADDR_TYPE_PUBLIC = 0x01, + ACI_BD_ADDR_TYPE_RANDOM_STATIC = 0x02, + ACI_BD_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE = 0x03, + ACI_BD_ADDR_TYPE_RANDOM_PRIVATE_UNRESOLVABLE = 0x04 +} _aci_packed_ aci_bd_addr_type_t; + +/** + * @enum aci_device_output_power_t + * @brief Radio output power levels + */ +typedef enum +{ + ACI_DEVICE_OUTPUT_POWER_MINUS_18DBM = 0x00, /**< Output power set to -18dBm */ + ACI_DEVICE_OUTPUT_POWER_MINUS_12DBM = 0x01, /**< Output power set to -12dBm */ + ACI_DEVICE_OUTPUT_POWER_MINUS_6DBM = 0x02, /**< Output power set to -6dBm */ + ACI_DEVICE_OUTPUT_POWER_0DBM = 0x03 /**< Output power set to 0dBm - DEFAULT*/ +} _aci_packed_ aci_device_output_power_t; + +/** + * @enum aci_device_operation_mode_t + * @brief Device operation modes + */ +typedef enum +{ + ACI_DEVICE_INVALID =0x00, + ACI_DEVICE_TEST =0x01, + ACI_DEVICE_SETUP =0x02, + ACI_DEVICE_STANDBY =0x03, + ACI_DEVICE_SLEEP =0x04 +} _aci_packed_ aci_device_operation_mode_t; + +/** + * @enum aci_disconnect_reason_t + * @brief Reason enumeration for ACI_CMD_DISCONNECT + */ +typedef enum +{ + ACI_REASON_TERMINATE =0x01, /**< Use this to disconnect (does a terminate request), you need to wait for the "disconnected" event */ + ACI_REASON_BAD_TIMING =0x02 /* Opcode of the ACI command */ + union + { + aci_cmd_params_test_t test; + aci_cmd_params_echo_t echo; + aci_cmd_params_dtm_cmd_t dtm_cmd; + aci_cmd_params_setup_t setup; + aci_cmd_params_write_dynamic_data_t write_dynamic_data; + aci_cmd_params_set_local_data_t set_local_data; + aci_cmd_params_connect_t connect; + aci_cmd_params_bond_t bond; + aci_cmd_params_disconnect_t disconnect; + aci_cmd_params_set_tx_power_t set_tx_power; + aci_cmd_params_change_timing_t change_timing; + aci_cmd_params_open_remote_pipe_t open_remote_pipe; + aci_cmd_params_send_data_t send_data; + aci_cmd_params_send_data_ack_t send_data_ack; + aci_cmd_params_request_data_t request_data; + aci_cmd_params_send_data_nack_t send_data_nack; + aci_cmd_params_set_app_latency_t set_app_latency; + aci_cmd_params_set_key_t set_key; + aci_cmd_params_open_adv_pipe_t open_adv_pipe; + aci_cmd_params_broadcast_t broadcast; + aci_cmd_params_close_remote_pipe_t close_remote_pipe; + + } params; +} _aci_packed_ aci_cmd_t; + +#endif /* ACI_CMDS_H__ */ diff --git a/Source/ble-caterina/BLE/aci_evts.h b/Source/ble-caterina/BLE/aci_evts.h new file mode 100644 index 0000000..4d5b934 --- /dev/null +++ b/Source/ble-caterina/BLE/aci_evts.h @@ -0,0 +1,397 @@ +/* Copyright (c) 2014, Nordic Semiconductor ASA + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/** + * @file + * + * @ingroup aci + * + * @brief Definitions for the ACI (Application Control Interface) events + */ + +#ifndef ACI_EVTS_H__ +#define ACI_EVTS_H__ + +#include "aci.h" + +/** + * @enum aci_evt_opcode_t + * @brief ACI event opcodes + */ +typedef enum +{ + /** + * Invalid event code + */ + ACI_EVT_INVALID = 0x00, + /** + * Sent every time the device starts + */ + ACI_EVT_DEVICE_STARTED = 0x81, + /** + * Mirrors the ACI_CMD_ECHO + */ + ACI_EVT_ECHO = 0x82, + /** + * Asynchronous hardware error event + */ + ACI_EVT_HW_ERROR = 0x83, + /** + * Event opcode used as a event response for all commands + */ + ACI_EVT_CMD_RSP = 0x84, + /** + * Link connected + */ + ACI_EVT_CONNECTED = 0x85, + /** + * Link disconnected + */ + ACI_EVT_DISCONNECTED = 0x86, + /** + * Bond completion result + */ + ACI_EVT_BOND_STATUS = 0x87, + /** + * Pipe bitmap for available pipes + */ + ACI_EVT_PIPE_STATUS = 0x88, + /** + * Sent to the application when the radio enters a connected state + * or when the timing of the radio connection changes + */ + ACI_EVT_TIMING = 0x89, + /** + * Notification to the application that transmit credits are + * available + */ + ACI_EVT_DATA_CREDIT = 0x8A, + /** + * Data acknowledgement event + */ + ACI_EVT_DATA_ACK = 0x8B, + /** + * Data received notification event + */ + ACI_EVT_DATA_RECEIVED = 0x8C, + /** + * Error notification event + */ + ACI_EVT_PIPE_ERROR = 0x8D, + /** + * Display Passkey Event + */ + ACI_EVT_DISPLAY_PASSKEY = 0x8E, + /** + * Security Key request + */ + ACI_EVT_KEY_REQUEST = 0x8F + +} _aci_packed_ aci_evt_opcode_t; + +ACI_ASSERT_SIZE(aci_evt_opcode_t, 1); + +/** + * @struct aci_evt_params_device_started_t + * @brief Structure for the ACI_EVT_DEVICE_STARTED event return parameters + */ +typedef struct +{ + aci_device_operation_mode_t device_mode; /**< Mode in which the device is being started */ + aci_hw_error_t hw_error; /**< Hardware Error if available for the start */ + uint8_t credit_available; /**< Flow control credit available for this specific FW build */ +} _aci_packed_ aci_evt_params_device_started_t; + +ACI_ASSERT_SIZE(aci_evt_params_device_started_t, 3); + +/** + * @struct aci_evt_params_hw_error_t + * @brief Structure for the ACI_EVT_HW_ERROR event return parameters + */ +typedef struct +{ + uint16_t line_num; + uint8_t file_name[20]; +} _aci_packed_ aci_evt_params_hw_error_t; + +ACI_ASSERT_SIZE(aci_evt_params_hw_error_t, 22); + +/** + * @struct aci_evt_cmd_rsp_params_dtm_cmd_t + * @brief Structure for the ACI_EVT_CMD_RSP event with opcode=ACI_CMD_DTM_CMD event return parameters + */ +typedef struct +{ + uint8_t evt_msb; + uint8_t evt_lsb; +} _aci_packed_ aci_evt_cmd_rsp_params_dtm_cmd_t; + +/** + * @struct aci_evt_cmd_rsp_read_dynamic_data_t + * @brief Structure for the ACI_EVT_CMD_RSP event with opcode=ACI_CMD_READ_DYNAMIC_DATA event return parameters + * @note Dynamic data chunk size in this event is defined to go up to ACI_PACKET_MAX_LEN - 5 + */ +typedef struct +{ + uint8_t seq_no; + uint8_t dynamic_data[1]; +} _aci_packed_ aci_evt_cmd_rsp_read_dynamic_data_t; + +/** + * @struct aci_evt_cmd_rsp_params_get_device_version_t + * @brief Structure for the ACI_EVT_CMD_RSP event with opcode=ACI_CMD_GET_DEVICE_VERSION event return parameters + */ +typedef struct +{ + uint16_t configuration_id; + uint8_t aci_version; + uint8_t setup_format; + uint32_t setup_id; + uint8_t setup_status; +} _aci_packed_ aci_evt_cmd_rsp_params_get_device_version_t; + +ACI_ASSERT_SIZE(aci_evt_cmd_rsp_params_get_device_version_t, 9); + +/** + * @struct aci_evt_cmd_rsp_params_get_device_address_t + * @brief Structure for the ACI_EVT_CMD_RSP event with opcode=ACI_CMD_GET_DEVICE_ADDRESS event return parameters + */ +typedef struct +{ + uint8_t bd_addr_own[BTLE_DEVICE_ADDRESS_SIZE]; + aci_bd_addr_type_t bd_addr_type; +} _aci_packed_ aci_evt_cmd_rsp_params_get_device_address_t; + +ACI_ASSERT_SIZE(aci_evt_cmd_rsp_params_get_device_address_t, BTLE_DEVICE_ADDRESS_SIZE + 1); + +/** + * @struct aci_evt_cmd_rsp_params_get_battery_level_t + * @brief Structure for the ACI_EVT_CMD_RSP event with opcode=ACI_CMD_GET_BATTERY_LEVEL event return parameters + */ +typedef struct +{ + uint16_t battery_level; +} _aci_packed_ aci_evt_cmd_rsp_params_get_battery_level_t; + +/** + * @struct aci_evt_cmd_rsp_params_get_temperature_t + * @brief Structure for the ACI_EVT_CMD_RSP event with opcode=ACI_CMD_GET_TEMPERATURE event return parameters + */ +typedef struct +{ + int16_t temperature_value; +} _aci_packed_ aci_evt_cmd_rsp_params_get_temperature_t; + +/** + * @struct aci_evt_params_cmd_rsp_t + * @brief Structure for the ACI_EVT_CMD_RSP event return parameters + */ +typedef struct +{ + aci_cmd_opcode_t cmd_opcode; /**< Command opcode for which the event response is being sent */ + aci_status_code_t cmd_status; /**< Status of the command that was sent. Used in the context of the command. */ + union + { + aci_evt_cmd_rsp_params_dtm_cmd_t dtm_cmd; + aci_evt_cmd_rsp_read_dynamic_data_t read_dynamic_data; + aci_evt_cmd_rsp_params_get_device_version_t get_device_version; + aci_evt_cmd_rsp_params_get_device_address_t get_device_address; + aci_evt_cmd_rsp_params_get_battery_level_t get_battery_level; + aci_evt_cmd_rsp_params_get_temperature_t get_temperature; + uint8_t padding[29]; + } params; +} _aci_packed_ aci_evt_params_cmd_rsp_t; + +ACI_ASSERT_SIZE(aci_evt_params_cmd_rsp_t, 31); + +/** + * @struct aci_evt_params_connected_t + * @brief Structure for the ACI_EVT_CONNECTED event return parameters + */ +typedef struct +{ + aci_bd_addr_type_t dev_addr_type; + uint8_t dev_addr[BTLE_DEVICE_ADDRESS_SIZE]; + uint16_t conn_rf_interval; /**< rf_interval = conn_rf_interval * 1.25 ms Range:0x0006 to 0x0C80 */ + uint16_t conn_slave_rf_latency; /**< Number of RF events the slave can skip */ + uint16_t conn_rf_timeout; /**< Timeout as a multiple of 10ms i.e timeout = conn_rf_timeout * 10ms Range: 0x000A to 0x0C80 */ + aci_clock_accuracy_t master_clock_accuracy; /**< Clock accuracy of Bluetooth master: Enumerated list of values from 500 ppm to 20 ppm */ +} _aci_packed_ aci_evt_params_connected_t; + +ACI_ASSERT_SIZE(aci_evt_params_connected_t, 14); + +/** + * @struct aci_evt_params_disconnected_t + * @brief Structure for the ACI_EVT_DISCONNECTED event return parameters + */ +typedef struct +{ + aci_status_code_t aci_status; + uint8_t btle_status; +} _aci_packed_ aci_evt_params_disconnected_t; + +ACI_ASSERT_SIZE(aci_evt_params_disconnected_t, 2); + +/** + * @struct aci_evt_params_bond_status_t + * @brief Structure for the ACI_EVT_BOND_STATUS event return parameters + */ +typedef struct +{ + aci_bond_status_code_t status_code; + aci_bond_status_source_t status_source; + uint8_t secmode1_bitmap; + uint8_t secmode2_bitmap; + uint8_t keys_exchanged_slave; + uint8_t keys_exchanged_master; +} _aci_packed_ aci_evt_params_bond_status_t; + +ACI_ASSERT_SIZE(aci_evt_params_bond_status_t, 6); + +/** + * @struct aci_evt_params_pipe_status_t + * @brief Structure for the ACI_EVT_PIPE_STATUS event return parameters + */ +typedef struct +{ + uint8_t pipes_open_bitmap[8]; + uint8_t pipes_closed_bitmap[8]; +} _aci_packed_ aci_evt_params_pipe_status_t; + +ACI_ASSERT_SIZE(aci_evt_params_pipe_status_t, 16); + +/** + * @struct aci_evt_params_timing_t + * @brief Structure for the ACI_EVT_TIMING event return parameters + */ +typedef struct +{ + uint16_t conn_rf_interval; /**< rf_interval = conn_rf_interval * 1.25 ms Range:0x0006 to 0x0C80 */ + uint16_t conn_slave_rf_latency; /**< Number of RF events the slave can skip */ + uint16_t conn_rf_timeout; /**< Timeout as a multiple of 10ms i.e timeout = conn_rf_timeout * 10ms Range: 0x000A to 0x0C80 */ +} _aci_packed_ aci_evt_params_timing_t; + +ACI_ASSERT_SIZE(aci_evt_params_timing_t, 6); + +/** + * @struct aci_evt_params_data_credit_t + * @brief Structure for the ACI_EVT_DATA_CREDIT event return parameters + */ +typedef struct +{ + uint8_t credit; +} _aci_packed_ aci_evt_params_data_credit_t; + +/** + * @struct aci_evt_params_data_ack_t + * @brief Structure for the ACI_EVT_DATA_ACK event return parameters + */ +typedef struct +{ + uint8_t pipe_number; +} _aci_packed_ aci_evt_params_data_ack_t; + +/** + * @struct aci_evt_params_data_received_t + * @brief Structure for the ACI_EVT_DATA_RECEIVED event return parameters + */ +typedef struct +{ + aci_rx_data_t rx_data; +} _aci_packed_ aci_evt_params_data_received_t; + +typedef struct +{ + uint8_t content[1]; +} _aci_packed_ error_data_t; + +/** + * @struct aci_evt_params_pipe_error_t + * @brief Structure for the ACI_EVT_PIPE_ERROR event return parameters + */ +typedef struct +{ + uint8_t pipe_number; + uint8_t error_code; + union + { + error_data_t error_data; + } params; +} _aci_packed_ aci_evt_params_pipe_error_t; + +/** + * @struct aci_evt_params_display_passkey_t + * @brief Structure for the ACI_EVT_DISPLAY_PASSKEY event return parameters + */ +typedef struct +{ + uint8_t passkey[6]; +} _aci_packed_ aci_evt_params_display_passkey_t; + +/** + * @struct aci_evt_params_key_request_t + * @brief Structure for the ACI_EVT_KEY_REQUEST event return parameters + */ +typedef struct +{ + aci_key_type_t key_type; +} _aci_packed_ aci_evt_params_key_request_t; + +/** + * @struct aci_event_params_echo_t + * @brief Structure for the ACI_EVT_ECHO ACI event parameters + */ +typedef struct +{ + uint8_t echo_data[ACI_ECHO_DATA_MAX_LEN]; +} _aci_packed_ aci_evt_params_echo_t; + +/** + * @struct aci_evt_t + * @brief Encapsulates a generic ACI event + */ +typedef struct +{ + uint8_t len; + aci_evt_opcode_t evt_opcode; + union + { + aci_evt_params_device_started_t device_started; + aci_evt_params_echo_t echo; + aci_evt_params_hw_error_t hw_error; + aci_evt_params_cmd_rsp_t cmd_rsp; + aci_evt_params_connected_t connected; + aci_evt_params_disconnected_t disconnected; + aci_evt_params_bond_status_t bond_status; + aci_evt_params_pipe_status_t pipe_status; + aci_evt_params_timing_t timing; + aci_evt_params_data_credit_t data_credit; + aci_evt_params_data_ack_t data_ack; + aci_evt_params_data_received_t data_received; + aci_evt_params_pipe_error_t pipe_error; + aci_evt_params_display_passkey_t display_passkey; + aci_evt_params_key_request_t key_request; + } params; +} _aci_packed_ aci_evt_t; + +ACI_ASSERT_SIZE(aci_evt_t, 33); + +#endif /* ACI_EVTS_H__ */ diff --git a/Source/ble-caterina/BLE/aci_protocol_defines.h b/Source/ble-caterina/BLE/aci_protocol_defines.h new file mode 100644 index 0000000..26add31 --- /dev/null +++ b/Source/ble-caterina/BLE/aci_protocol_defines.h @@ -0,0 +1,187 @@ +/* Copyright (c) 2014, Nordic Semiconductor ASA + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +/* + * This file contents defines for the position of all the fields of ACI + * command or event messages + */ + +#ifndef ACI_OFFSET_H__ +#define ACI_OFFSET_H__ + + +#define OFFSET_ACI_LL_CONN_PARAMS_T_MIN_CONN_INTERVAL_LSB 0 +#define OFFSET_ACI_LL_CONN_PARAMS_T_MIN_CONN_INTERVAL_MSB 1 +#define OFFSET_ACI_LL_CONN_PARAMS_T_MAX_CONN_INTERVAL_LSB 2 +#define OFFSET_ACI_LL_CONN_PARAMS_T_MAX_CONN_INTERVAL_MSB 3 +#define OFFSET_ACI_LL_CONN_PARAMS_T_SLAVE_LATENCY_LSB 4 +#define OFFSET_ACI_LL_CONN_PARAMS_T_SLAVE_LATENCY_MSB 5 +#define OFFSET_ACI_LL_CONN_PARAMS_T_TIMEOUT_MULT_LSB 6 +#define OFFSET_ACI_LL_CONN_PARAMS_T_TIMEOUT_MULT_MSB 7 +#define OFFSET_ACI_TX_DATA_T_PIPE_NUMBER 0 +#define OFFSET_ACI_TX_DATA_T_ACI_DATA 1 +#define OFFSET_ACI_RX_DATA_T_PIPE_NUMBER 0 +#define OFFSET_ACI_RX_DATA_T_ACI_DATA 1 +#define OFFSET_ACI_CMD_PARAMS_TEST_T_TEST_MODE_CHANGE 0 +#define OFFSET_ACI_CMD_PARAMS_ECHO_T_ECHO_DATA 0 +#define OFFSET_ACI_CMD_PARAMS_DTM_CMD_T_CMD_MSB 0 +#define OFFSET_ACI_CMD_PARAMS_DTM_CMD_T_CMD_LSB 1 +#define OFFSET_ACI_CMD_PARAMS_SETUP_T_SETUP_DATA 0 +#define OFFSET_ACI_CMD_PARAMS_WRITE_DYNAMIC_DATA_T_SEQ_NO 0 +#define OFFSET_ACI_CMD_PARAMS_WRITE_DYNAMIC_DATA_T_DYNAMIC_DATA 1 +#define OFFSET_ACI_CMD_PARAMS_SET_LOCAL_DATA_T_TX_DATA 0 +#define OFFSET_ACI_CMD_PARAMS_CONNECT_T_TIMEOUT_LSB 0 +#define OFFSET_ACI_CMD_PARAMS_CONNECT_T_TIMEOUT_MSB 1 +#define OFFSET_ACI_CMD_PARAMS_CONNECT_T_ADV_INTERVAL_LSB 2 +#define OFFSET_ACI_CMD_PARAMS_CONNECT_T_ADV_INTERVAL_MSB 3 +#define OFFSET_ACI_CMD_PARAMS_BOND_T_TIMEOUT_LSB 0 +#define OFFSET_ACI_CMD_PARAMS_BOND_T_TIMEOUT_MSB 1 +#define OFFSET_ACI_CMD_PARAMS_BOND_T_ADV_INTERVAL_LSB 2 +#define OFFSET_ACI_CMD_PARAMS_BOND_T_ADV_INTERVAL_MSB 3 +#define OFFSET_ACI_CMD_PARAMS_DISCONNECT_T_REASON 0 +#define OFFSET_ACI_CMD_PARAMS_SET_TX_POWER_T_DEVICE_POWER 0 +#define OFFSET_ACI_CMD_PARAMS_CHANGE_TIMING_T_CONN_PARAMS 0 +#define OFFSET_ACI_CMD_PARAMS_OPEN_REMOTE_PIPE_T_PIPE_NUMBER 0 +#define OFFSET_ACI_CMD_PARAMS_SEND_DATA_T_TX_DATA 0 +#define OFFSET_ACI_CMD_PARAMS_SEND_DATA_ACK_T_PIPE_NUMBER 0 +#define OFFSET_ACI_CMD_PARAMS_REQUEST_DATA_T_PIPE_NUMBER 0 +#define OFFSET_ACI_CMD_PARAMS_SEND_DATA_NACK_T_PIPE_NUMBER 0 +#define OFFSET_ACI_CMD_PARAMS_SEND_DATA_NACK_T_ERROR_CODE 1 +#define OFFSET_ACI_CMD_PARAMS_SET_APP_LATENCY_T_MODE 0 +#define OFFSET_ACI_CMD_PARAMS_SET_APP_LATENCY_T_LATENCY_LSB 1 +#define OFFSET_ACI_CMD_PARAMS_SET_APP_LATENCY_T_LATENCY_MSB 2 +#define OFFSET_ACI_CMD_PARAMS_SET_KEY_T_KEY_TYPE 0 +#define OFFSET_ACI_CMD_PARAMS_SET_KEY_T_PASSKEY 1 +#define OFFSET_ACI_CMD_PARAMS_SET_KEY_T_OOB_KEY 1 +#define OFFSET_ACI_CMD_PARAMS_OPEN_ADV_PIPE_T_PIPES 0 +#define OFFSET_ACI_CMD_PARAMS_BROADCAST_T_TIMEOUT_LSB 0 +#define OFFSET_ACI_CMD_PARAMS_BROADCAST_T_TIMEOUT_MSB 1 +#define OFFSET_ACI_CMD_PARAMS_BROADCAST_T_ADV_INTERVAL_LSB 2 +#define OFFSET_ACI_CMD_PARAMS_BROADCAST_T_ADV_INTERVAL_MSB 3 +#define OFFSET_ACI_CMD_PARAMS_CLOSE_REMOTE_PIPE_T_PIPE_NUMBER 0 +#define OFFSET_ACI_CMD_T_LEN 0 +#define OFFSET_ACI_CMD_T_CMD_OPCODE 1 +#define OFFSET_ACI_CMD_T_TEST 2 +#define OFFSET_ACI_CMD_T_ECHO 2 +#define OFFSET_ACI_CMD_T_DTM_CMD 2 +#define OFFSET_ACI_CMD_T_SETUP 2 +#define OFFSET_ACI_CMD_T_WRITE_DYNAMIC_DATA 2 +#define OFFSET_ACI_CMD_T_SET_LOCAL_DATA 2 +#define OFFSET_ACI_CMD_T_CONNECT 2 +#define OFFSET_ACI_CMD_T_BOND 2 +#define OFFSET_ACI_CMD_T_DISCONNECT 2 +#define OFFSET_ACI_CMD_T_SET_TX_POWER 2 +#define OFFSET_ACI_CMD_T_CHANGE_TIMING 2 +#define OFFSET_ACI_CMD_T_OPEN_REMOTE_PIPE 2 +#define OFFSET_ACI_CMD_T_SEND_DATA 2 +#define OFFSET_ACI_CMD_T_SEND_DATA_ACK 2 +#define OFFSET_ACI_CMD_T_REQUEST_DATA 2 +#define OFFSET_ACI_CMD_T_SEND_DATA_NACK 2 +#define OFFSET_ACI_CMD_T_SET_APP_LATENCY 2 +#define OFFSET_ACI_CMD_T_SET_KEY 2 +#define OFFSET_ACI_CMD_T_OPEN_ADV_PIPE 2 +#define OFFSET_ACI_CMD_T_BROADCAST 2 +#define OFFSET_ACI_CMD_T_CLOSE_REMOTE_PIPE 2 +#define OFFSET_ACI_EVT_PARAMS_DEVICE_STARTED_T_DEVICE_MODE 0 +#define OFFSET_ACI_EVT_PARAMS_DEVICE_STARTED_T_HW_ERROR 1 +#define OFFSET_ACI_EVT_PARAMS_DEVICE_STARTED_T_CREDIT_AVAILABLE 2 +#define OFFSET_ACI_EVT_PARAMS_HW_ERROR_T_LINE_NUM_LSB 0 +#define OFFSET_ACI_EVT_PARAMS_HW_ERROR_T_LINE_NUM_MSB 1 +#define OFFSET_ACI_EVT_PARAMS_HW_ERROR_T_FILE_NAME 2 +#define OFFSET_ACI_EVT_CMD_RSP_PARAMS_DTM_CMD_T_EVT_MSB 0 +#define OFFSET_ACI_EVT_CMD_RSP_PARAMS_DTM_CMD_T_EVT_LSB 1 +#define OFFSET_ACI_EVT_CMD_RSP_READ_DYNAMIC_DATA_T_SEQ_NO 0 +#define OFFSET_ACI_EVT_CMD_RSP_READ_DYNAMIC_DATA_T_DYNAMIC_DATA 1 +#define OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_DEVICE_VERSION_T_CONFIGURATION_ID_LSB 0 +#define OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_DEVICE_VERSION_T_CONFIGURATION_ID_MSB 1 +#define OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_DEVICE_VERSION_T_ACI_VERSION 2 +#define OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_DEVICE_VERSION_T_SETUP_FORMAT 3 +#define OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_DEVICE_VERSION_T_SETUP_ID_LSB0 4 +#define OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_DEVICE_VERSION_T_SETUP_ID_LSB1 5 +#define OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_DEVICE_VERSION_T_SETUP_ID_MSB0 6 +#define OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_DEVICE_VERSION_T_SETUP_ID_MSB1 7 +#define OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_DEVICE_VERSION_T_SETUP_STATUS 8 +#define OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_DEVICE_ADDRESS_T_BD_ADDR_OWN 0 +#define OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_DEVICE_ADDRESS_T_BD_ADDR_TYPE 6 +#define OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_BATTERY_LEVEL_T_BATTERY_LEVEL_LSB 0 +#define OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_BATTERY_LEVEL_T_BATTERY_LEVEL_MSB 1 +#define OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_TEMPERATURE_T_TEMPERATURE_VALUE_LSB 0 +#define OFFSET_ACI_EVT_CMD_RSP_PARAMS_GET_TEMPERATURE_T_TEMPERATURE_VALUE_MSB 1 +#define OFFSET_ACI_EVT_PARAMS_CMD_RSP_T_CMD_OPCODE 0 +#define OFFSET_ACI_EVT_PARAMS_CMD_RSP_T_CMD_STATUS 1 +#define OFFSET_ACI_EVT_PARAMS_CMD_RSP_T_DTM_CMD 2 +#define OFFSET_ACI_EVT_PARAMS_CMD_RSP_T_READ_DYNAMIC_DATA 2 +#define OFFSET_ACI_EVT_PARAMS_CMD_RSP_T_GET_DEVICE_VERSION 2 +#define OFFSET_ACI_EVT_PARAMS_CMD_RSP_T_GET_DEVICE_ADDRESS 2 +#define OFFSET_ACI_EVT_PARAMS_CMD_RSP_T_GET_BATTERY_LEVEL 2 +#define OFFSET_ACI_EVT_PARAMS_CMD_RSP_T_GET_TEMPERATURE 2 +#define OFFSET_ACI_EVT_PARAMS_CONNECTED_T_DEV_ADDR_TYPE 0 +#define OFFSET_ACI_EVT_PARAMS_CONNECTED_T_DEV_ADDR 1 +#define OFFSET_ACI_EVT_PARAMS_CONNECTED_T_CONN_RF_INTERVAL_LSB 7 +#define OFFSET_ACI_EVT_PARAMS_CONNECTED_T_CONN_RF_INTERVAL_MSB 8 +#define OFFSET_ACI_EVT_PARAMS_CONNECTED_T_CONN_SLAVE_RF_LATENCY_LSB 9 +#define OFFSET_ACI_EVT_PARAMS_CONNECTED_T_CONN_SLAVE_RF_LATENCY_MSB 10 +#define OFFSET_ACI_EVT_PARAMS_CONNECTED_T_CONN_RF_TIMEOUT_LSB 11 +#define OFFSET_ACI_EVT_PARAMS_CONNECTED_T_CONN_RF_TIMEOUT_MSB 12 +#define OFFSET_ACI_EVT_PARAMS_CONNECTED_T_MASTER_CLOCK_ACCURACY 13 +#define OFFSET_ACI_EVT_PARAMS_DISCONNECTED_T_ACI_STATUS 0 +#define OFFSET_ACI_EVT_PARAMS_DISCONNECTED_T_BTLE_STATUS 1 +#define OFFSET_ACI_EVT_PARAMS_BOND_STATUS_T_STATUS_CODE 0 +#define OFFSET_ACI_EVT_PARAMS_BOND_STATUS_T_STATUS_SOURCE 1 +#define OFFSET_ACI_EVT_PARAMS_BOND_STATUS_T_SECMODE1_BITMAP 2 +#define OFFSET_ACI_EVT_PARAMS_BOND_STATUS_T_SECMODE2_BITMAP 3 +#define OFFSET_ACI_EVT_PARAMS_BOND_STATUS_T_KEYS_EXCHANGED_SLAVE 4 +#define OFFSET_ACI_EVT_PARAMS_BOND_STATUS_T_KEYS_EXCHANGED_MASTER 5 +#define OFFSET_ACI_EVT_PARAMS_PIPE_STATUS_T_PIPES_OPEN_BITMAP 0 +#define OFFSET_ACI_EVT_PARAMS_PIPE_STATUS_T_PIPES_CLOSED_BITMAP 8 +#define OFFSET_ACI_EVT_PARAMS_TIMING_T_CONN_RF_INTERVAL_LSB 0 +#define OFFSET_ACI_EVT_PARAMS_TIMING_T_CONN_RF_INTERVAL_MSB 1 +#define OFFSET_ACI_EVT_PARAMS_TIMING_T_CONN_SLAVE_RF_LATENCY_LSB 2 +#define OFFSET_ACI_EVT_PARAMS_TIMING_T_CONN_SLAVE_RF_LATENCY_MSB 3 +#define OFFSET_ACI_EVT_PARAMS_TIMING_T_CONN_RF_TIMEOUT_LSB 4 +#define OFFSET_ACI_EVT_PARAMS_TIMING_T_CONN_RF_TIMEOUT_MSB 5 +#define OFFSET_ACI_EVT_PARAMS_DATA_CREDIT_T_CREDIT 0 +#define OFFSET_ACI_EVT_PARAMS_DATA_ACK_T_PIPE_NUMBER 0 +#define OFFSET_ACI_EVT_PARAMS_DATA_RECEIVED_T_RX_DATA 0 +#define OFFSET_ERROR_DATA_T_CONTENT 0 +#define OFFSET_ACI_EVT_PARAMS_PIPE_ERROR_T_PIPE_NUMBER 0 +#define OFFSET_ACI_EVT_PARAMS_PIPE_ERROR_T_ERROR_CODE 1 +#define OFFSET_ACI_EVT_PARAMS_PIPE_ERROR_T_ERROR_DATA 2 +#define OFFSET_ACI_EVT_PARAMS_DISPLAY_PASSKEY_T_PASSKEY 0 +#define OFFSET_ACI_EVT_PARAMS_KEY_REQUEST_T_KEY_TYPE 0 +#define OFFSET_ACI_EVT_T_LEN 0 +#define OFFSET_ACI_EVT_T_EVT_OPCODE 1 +#define OFFSET_ACI_EVT_T_DEVICE_STARTED 2 +#define OFFSET_ACI_EVT_T_HW_ERROR 2 +#define OFFSET_ACI_EVT_T_CMD_RSP 2 +#define OFFSET_ACI_EVT_T_CONNECTED 2 +#define OFFSET_ACI_EVT_T_DISCONNECTED 2 +#define OFFSET_ACI_EVT_T_BOND_STATUS 2 +#define OFFSET_ACI_EVT_T_PIPE_STATUS 2 +#define OFFSET_ACI_EVT_T_TIMING 2 +#define OFFSET_ACI_EVT_T_DATA_CREDIT 2 +#define OFFSET_ACI_EVT_T_DATA_ACK 2 +#define OFFSET_ACI_EVT_T_DATA_RECEIVED 2 +#define OFFSET_ACI_EVT_T_PIPE_ERROR 2 +#define OFFSET_ACI_EVT_T_DISPLAY_PASSKEY 2 +#define OFFSET_ACI_EVT_T_KEY_REQUEST 2 + +#endif /* ACI_OFFSET_H__ */ diff --git a/Source/ble-caterina/BLE/aci_setup.c b/Source/ble-caterina/BLE/aci_setup.c new file mode 100644 index 0000000..7670b8f --- /dev/null +++ b/Source/ble-caterina/BLE/aci_setup.c @@ -0,0 +1,163 @@ +/* Copyright (c) 2014, Nordic Semiconductor ASA + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "lib_aci.h" +#include "aci_setup.h" + +extern bool need_tx; +extern bool rx_ready; + +// aci_struct that will contain +// total initial credits +// current credit +// current state of the aci (setup/standby/active/sleep) +// open remote pipe pending +// close remote pipe pending +// Current pipe available bitmap +// Current pipe closed bitmap +// Current connection interval, slave latency and link supervision timeout +// Current State of the the GATT client (Service Discovery status) + +/************************************************************************** */ +/* Utility function to fill the the ACI command queue */ +/* aci_stat Pointer to the ACI state */ +/* num_cmd_offset(in/out) Offset in the Setup message array to start from */ +/* offset is updated to the new index after the queue is filled */ +/* or the last message us placed in the queue */ +/* Returns true if at least one message was transferred */ +/***************************************************************************/ +static bool aci_setup_fill(aci_state_t *aci_stat, uint8_t *num_cmd_offset) +{ + bool ret_val = false; + hal_aci_data_t msg_to_send; + + while (*num_cmd_offset < aci_stat->aci_setup_info.num_setup_msgs) + { + //Board dependent defines + //For Arduino copy the setup ACI message from Flash to RAM. + memcpy_P(&msg_to_send, &(aci_stat->aci_setup_info.setup_msgs[*num_cmd_offset]), + pgm_read_byte_near(&(aci_stat->aci_setup_info.setup_msgs[*num_cmd_offset].buffer[0]))+2); + + //Put the Setup ACI message in the command queue + if (!hal_aci_tl_send(&msg_to_send)) + { + //ACI Command Queue is full + // *num_cmd_offset is now pointing to the index of the Setup command that did not get sent + return ret_val; + } + + ret_val = true; + + (*num_cmd_offset)++; + } + + return ret_val; +} + +uint8_t do_aci_setup(aci_state_t *aci_stat) +{ + uint8_t setup_offset = 0; +// uint32_t i = 0x0000; + aci_evt_t * aci_evt; + aci_status_code_t cmd_status = ACI_STATUS_ERROR_CRC_MISMATCH; + + /* + We are using the same buffer since we are copying the contents of the buffer + when queuing and immediately processing the buffer when receiving + */ + hal_aci_evt_t aci_data; + + /* Messages in the outgoing queue must be handled before the Setup routine can run. + * If it is non-empty we return. The user should then process the messages before calling + * do_aci_setup() again. + */ +// if (need_tx) +// { +// Serial.println("return SETUP_FAIL_COMMAND_QUEUE_NOT_EMPTY;"); +// return SETUP_FAIL_COMMAND_QUEUE_NOT_EMPTY; +// } + + /* If there are events pending from the device that are not relevant to setup, we return false + * so that the user can handle them. At this point we don't care what the event is, + * as any event is an error. + */ +// if (lib_aci_event_peek(&aci_data)) +// { +// Serial.println("return SETUP_FAIL_EVENT_QUEUE_NOT_EMPTY;"); +// return SETUP_FAIL_EVENT_QUEUE_NOT_EMPTY; +// } + + /* Fill the ACI command queue with as many Setup messages as it will hold. */ + aci_setup_fill(aci_stat, &setup_offset); + + + while (cmd_status != ACI_STATUS_TRANSACTION_COMPLETE) + { + /* This counter is used to ensure that this function does not loop forever. When the device + * returns a valid response, we reset the counter. + */ +// if (i++ > 0xFFFFE) +// { +// Serial.println("return SETUP_FAIL_TIMEOUT;"); +// return SETUP_FAIL_TIMEOUT; +// } + + if (lib_aci_event_peek(&aci_data)) + { + aci_evt = &(aci_data.evt); + +// if (ACI_EVT_CMD_RSP != aci_evt->evt_opcode) +// { +// Serial.println("return SETUP_FAIL_NOT_COMMAND_RESPONSE;"); +// //Receiving something other than a Command Response Event is an error. +// return SETUP_FAIL_NOT_COMMAND_RESPONSE; +// } + + cmd_status = (aci_status_code_t) aci_evt->params.cmd_rsp.cmd_status; + switch (cmd_status) + { + case ACI_STATUS_TRANSACTION_CONTINUE: + //As the device is responding, reset guard counter +// i = 0; + + /* As the device has processed the Setup messages we put in the command queue earlier, + * we can proceed to fill the queue with new messages + */ + aci_setup_fill(aci_stat, &setup_offset); + // Send the data to nRF8001 + lib_aci_event_get (aci_stat, &aci_data); + break; + + case ACI_STATUS_TRANSACTION_COMPLETE: + //Break out of the while loop when this status code appears + break; + + default: + //An event with any other status code should be handled by the application + return SETUP_FAIL_NOT_SETUP_EVENT; + } + } + } + + return SETUP_SUCCESS; +} + + diff --git a/Source/ble-caterina/BLE/aci_setup.h b/Source/ble-caterina/BLE/aci_setup.h new file mode 100644 index 0000000..3261f76 --- /dev/null +++ b/Source/ble-caterina/BLE/aci_setup.h @@ -0,0 +1,44 @@ +/* Copyright (c) 2014, Nordic Semiconductor ASA + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + +#ifndef H_ACI_SETUP +#define H_ACI_SETUP + +#define SETUP_SUCCESS 0 +#define SETUP_FAIL_COMMAND_QUEUE_NOT_EMPTY 1 +#define SETUP_FAIL_EVENT_QUEUE_NOT_EMPTY 2 +#define SETUP_FAIL_TIMEOUT 3 +#define SETUP_FAIL_NOT_SETUP_EVENT 4 +#define SETUP_FAIL_NOT_COMMAND_RESPONSE 5 + +/** @brief Setup the nRF8001 device + * @details + * Performs ACI Setup by transmitting the setup messages generated by nRFgo Studio to the + * nRF8001, and should be called when the nRF8001 starts or resets. + * Once all messages are sent, the nRF8001 will send a Device Started Event. + * The function requires that the Command queue is empty when it is invoked, and will fail + * otherwise. + * @returns An integer indicating the reason the function terminated + */ +uint8_t do_aci_setup(aci_state_t *aci_stat); + +#endif diff --git a/Source/ble-caterina/BLE/acilib.h b/Source/ble-caterina/BLE/acilib.h new file mode 100644 index 0000000..5f901dd --- /dev/null +++ b/Source/ble-caterina/BLE/acilib.h @@ -0,0 +1,61 @@ +/* Copyright (c) 2014, Nordic Semiconductor ASA + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/** + * @file + * + * @ingroup group_acilib + * + * @brief Internal prototype for acilib module. + */ + +#ifndef _acilib_H_ +#define _acilib_H_ + +#define MSG_SET_LOCAL_DATA_BASE_LEN 2 +#define MSG_CONNECT_LEN 5 +#define MSG_BOND_LEN 5 +#define MSG_DISCONNECT_LEN 2 +#define MSG_BASEBAND_RESET_LEN 1 +#define MSG_WAKEUP_LEN 1 +#define MSG_SET_RADIO_TX_POWER_LEN 2 +#define MSG_GET_DEVICE_ADDR_LEN 1 +#define MSG_SEND_DATA_BASE_LEN 2 +#define MSG_DATA_REQUEST_LEN 2 +#define MSG_OPEN_REMOTE_PIPE_LEN 2 +#define MSG_CLOSE_REMOTE_PIPE_LEN 2 +#define MSG_DTM_CMD 3 +#define MSG_WRITE_DYNAMIC_DATA_BASE_LEN 2 +#define MSG_SETUP_CMD_BASE_LEN 1 +#define MSG_ECHO_MSG_CMD_BASE_LEN 1 +#define MSG_CHANGE_TIMING_LEN 9 +#define MSG_SET_APP_LATENCY_LEN 4 +#define MSG_CHANGE_TIMING_LEN_GAP_PPCP 1 +#define MSG_DIRECT_CONNECT_LEN 1 +#define MSG_SET_KEY_REJECT_LEN 2 +#define MSG_SET_KEY_PASSKEY_LEN 8 +#define MSG_SET_KEY_OOB_LEN 18 +#define MSG_ACK_LEN 2 +#define MSG_NACK_LEN 3 +#define MSG_BROADCAST_LEN 5 +#define MSG_OPEN_ADV_PIPES_LEN 9 + +#endif /* _acilib_H_ */ diff --git a/Source/ble-caterina/BLE/acilib_defs.h b/Source/ble-caterina/BLE/acilib_defs.h new file mode 100644 index 0000000..25826d2 --- /dev/null +++ b/Source/ble-caterina/BLE/acilib_defs.h @@ -0,0 +1,37 @@ +/* Copyright (c) 2014, Nordic Semiconductor ASA + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/** + * @file + * + * @ingroup group_acilib + * + * @brief Definitions for the acilib interfaces + */ + +#ifndef _acilib_DEFS_H_ +#define _acilib_DEFS_H_ + +#define ACIL_DECODE_EVT_GET_LENGTH(buffer_in) (*(buffer_in + OFFSET_ACI_EVT_T_LEN)) + +#define ACIL_DECODE_EVT_GET_OPCODE(buffer_in) (*(buffer_in + OFFSET_ACI_EVT_T_EVT_OPCODE)) + +#endif /* _acilib_DEFS_H_ */ diff --git a/Source/ble-caterina/BLE/acilib_if.h b/Source/ble-caterina/BLE/acilib_if.h new file mode 100644 index 0000000..1499a54 --- /dev/null +++ b/Source/ble-caterina/BLE/acilib_if.h @@ -0,0 +1,65 @@ +/* Copyright (c) 2014, Nordic Semiconductor ASA + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/** + * @file + * + * @ingroup group_acilib + * + * @brief Prototypes for the acilib interfaces. + */ + +#ifndef _acilib_IF_H_ +#define _acilib_IF_H_ + +#include + +#include "aci_cmds.h" + +/** @brief Encode the ACI message to connect + * + * @param[in,out] buffer Pointer to ACI message buffer + * @param[in] p_aci_cmd_params_connect Pointer to the run parameters in ::aci_cmd_params_connect_t + * + * @return None + */ +void acil_encode_cmd_connect(uint8_t *buffer, aci_cmd_params_connect_t *p_aci_cmd_params_connect); + +/** @brief Encode the ACI message to disconnect + * + * @param[in,out] buffer Pointer to ACI message buffer + * @param[in] p_aci_cmd_params_disconnect Pointer to the run parameters in ::aci_cmd_params_disconnect_t + * + * @return None + */ +void acil_encode_cmd_disconnect(uint8_t *buffer, aci_cmd_params_disconnect_t *p_aci_cmd_params_disconnect); + +/** @brief Encode the ACI message for send data + * + * @param[in,out] buffer Pointer to ACI message buffer + * @param[in] p_aci_cmd_params_send_data_t Pointer to the data parameters in ::aci_cmd_params_send_data_t + * @param[in] data_size Size of data message + * + * @return None + */ +void acil_encode_cmd_send_data(uint8_t *buffer, aci_cmd_params_send_data_t *p_aci_cmd_params_send_data_t, uint8_t data_size); + +#endif diff --git a/Source/ble-caterina/BLE/dfu.c b/Source/ble-caterina/BLE/dfu.c new file mode 100644 index 0000000..995ebe0 --- /dev/null +++ b/Source/ble-caterina/BLE/dfu.c @@ -0,0 +1,401 @@ +/* Copyright (c) 2014, Nordic Semiconductor ASA + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/** @file + @brief Implementation of the DFU procedure. + */ + +#include "Caterina.h" + +#include +#include +#include + +#include "lib_aci.h" +#include "dfu.h" + +/***************************************************************************** +* Local definitions +*****************************************************************************/ + +static void dfu_data_pkt_handle (aci_evt_t *aci_evt); +static void dfu_init_pkt_handle (aci_evt_t *aci_evt); +static void dfu_image_size_set (aci_evt_t *aci_evt); +static void dfu_image_validate (aci_evt_t *aci_evt); + +static void m_notify (void); +static bool m_send (uint8_t *buff, uint8_t buff_len); +static void m_write_page (uint16_t page, uint8_t *buff); + +/***************************************************************************** +* Static Globals +*****************************************************************************/ + +static aci_state_t *m_aci_state; +static uint8_t m_dfu_state = ST_ANY; +static uint32_t m_image_size; +static uint16_t m_pkt_notif_target; +static uint16_t m_pkt_notif_target_cnt; +static uint32_t m_num_of_firmware_bytes_rcvd; +static uint16_t m_page_address; +static uint8_t m_page_buff[SPM_PAGESIZE]; +static uint8_t m_page_buff_index; +static uint8_t m_pipe_array[3]; + +extern bool RunBootloader; + +/***************************************************************************** +* Static Functions +*****************************************************************************/ + +/* Send receive notification with number of bytes received */ +static void m_notify (void) +{ + uint8_t response[] = {OP_CODE_PKT_RCPT_NOTIF, + 0, + (uint8_t) (m_num_of_firmware_bytes_rcvd >> 0), + (uint8_t) (m_num_of_firmware_bytes_rcvd >> 8), + (uint8_t) (m_num_of_firmware_bytes_rcvd >> 16), + (uint8_t) (m_num_of_firmware_bytes_rcvd >> 24)}; + + while(!m_send (response, sizeof(response))); +} + +/* Transmit buffer_len number of bytes from buffer to the BLE controller */ +static bool m_send (uint8_t *buff, uint8_t buff_len) +{ + bool status; + + // Abort if the notification pipe isn't available + /*if (!lib_aci_is_pipe_available (m_aci_state, m_pipe_array[1])) + { + return false; + }*/ + + // Abort if we don't have the necessary credit to transmit +// if (m_aci_state->data_credit_available == 0) +// { +// return false; +// } + + // Put the notification message in the queue + status = lib_aci_send_data(m_pipe_array[1], buff, buff_len); + + // Decrement our credit if we successfully transmitted + if (status) + { + m_aci_state->data_credit_available--; + } + + TX_LED_TOGGLE(); + + return status; +} + +/* Write the contents of buf to the given flash page */ +static void m_write_page (uint16_t page_num, uint8_t *buff) +{ + uint16_t i; + uint16_t word; + + /* Disable timer 1 interrupt - can't afford to process nonessential interrupts while doing SPM tasks */ + TIMSK1 = 0; + + // Erase flash page, then wait while the memory is written + boot_page_erase(page_num); + boot_spm_busy_wait(); + + // Fill the page buffer + for (i = 0; i < SPM_PAGESIZE; i += 2) + { + // Set up little-endian word. + word = *buff++; + word += (*buff++) << 8; + + boot_page_fill(page_num + i, word); + } + + // Store buffer in flash page, then wait while the memory is written + boot_page_write(page_num); + boot_spm_busy_wait(); + + // Reenable RWW-section again. We need this if we want to jump back + // to the application after bootloading. + boot_rww_enable(); + + /* Re-enable timer 1 interrupt disabled earlier in this routine */ + TIMSK1 = (1 << OCIE1A); +} + +/* Receive a firmware packet, and write it to flash. Also sends receipt + * notifications if needed + */ +static void dfu_data_pkt_handle (aci_evt_t *aci_evt) +{ + static uint8_t response[] = { OP_CODE_RESPONSE, + BLE_DFU_RECEIVE_APP_PROCEDURE, + BLE_DFU_RESP_VAL_SUCCESS}; + + aci_evt_params_data_received_t *data_received; + uint8_t bytes_received = aci_evt->len-2; + uint8_t i; + + // If package notification is enabled, decrement the counter and issue a + // notification if required + if (m_pkt_notif_target) + { + m_pkt_notif_target_cnt--; + + // Notification is required. Issue notification and reset counter + if (m_pkt_notif_target_cnt == 0) + { + m_pkt_notif_target_cnt = m_pkt_notif_target; + m_notify (); + } + } + + // Write received data to page buffer. When the buffer is full, write the + // buffer to flash. + data_received = (aci_evt_params_data_received_t *) &(aci_evt->params); + for (i = 0; i < bytes_received; i++) + { + m_page_buff[m_page_buff_index++] = data_received->rx_data.aci_data[i]; + + if (m_page_buff_index == SPM_PAGESIZE) + { + m_page_buff_index = 0; + m_write_page (m_page_address, m_page_buff); + m_page_address += SPM_PAGESIZE; + } + } + + // Check if we've received the entire firmware image + m_num_of_firmware_bytes_rcvd += bytes_received; + if (m_image_size == m_num_of_firmware_bytes_rcvd) + { + // Write final page to flash + m_write_page (m_page_address++, m_page_buff); + + // Send firmware received notification + while(!m_send (response, sizeof(response))); + } +} + +/* Receive and process an init packet */ +static void dfu_init_pkt_handle (aci_evt_t *aci_evt) +{ + static uint8_t response[] = {OP_CODE_RESPONSE, + BLE_DFU_INIT_PROCEDURE, + BLE_DFU_RESP_VAL_SUCCESS}; + + // Send init received notification + while(!m_send (response, sizeof(response))); +} + +/* Receive and store the firmware image size */ +static void dfu_image_size_set (aci_evt_t *aci_evt) +{ + const uint8_t pipe = m_pipe_array[1]; + const uint8_t byte_idx = pipe / 8; + static uint8_t response[] = {OP_CODE_RESPONSE, BLE_DFU_START_PROCEDURE, + BLE_DFU_RESP_VAL_SUCCESS}; + + // There are two paths into the bootloader. We either got here because + // there is no application, or we jumped from application. + // In the latter case, as we haven't received an event from the nRF8001 + // with the pipe statuses, we have to assume that the Control Point + // TX pipe is open. At this point, that is safe. + m_aci_state->pipes_open_bitmap[byte_idx] |= (1 << (pipe % 8)); + m_aci_state->pipes_closed_bitmap[byte_idx] &= ~(1 << (pipe % 8)); + + m_image_size = + (uint32_t)aci_evt->params.data_received.rx_data.aci_data[3] << 24 | + (uint32_t)aci_evt->params.data_received.rx_data.aci_data[2] << 16 | + (uint32_t)aci_evt->params.data_received.rx_data.aci_data[1] << 8 | + (uint32_t)aci_evt->params.data_received.rx_data.aci_data[0]; + + if(m_image_size == 0 || m_image_size > 28672) + { + response[2] = BLE_DFU_RESP_VAL_DATA_SIZE; + } + else + { + m_dfu_state = ST_RDY; + } + + // Write response + while(!m_send (response, sizeof(response))); +} + +/* Activate the received firmware image */ +static void dfu_image_activate (aci_evt_t *aci_evt) +{ + hal_aci_evt_t aci_data; + aci_evt_t *aci_evt_m; + + lib_aci_disconnect(m_aci_state, ACI_REASON_TERMINATE); + + while( !(aci_evt_m->evt_opcode == ACI_EVT_DISCONNECTED) ) + { + lib_aci_event_get(m_aci_state, &aci_data); + aci_evt_m = &(aci_data.evt); + } + + RunBootloader = false; +} + +/* Validate the received firmware image, and transmit the result */ +static void dfu_image_validate (aci_evt_t *aci_evt) +{ + uint8_t response[] = {OP_CODE_RESPONSE, + BLE_DFU_VALIDATE_PROCEDURE, + BLE_DFU_RESP_VAL_SUCCESS}; + + // Completed successfully + if (m_num_of_firmware_bytes_rcvd == m_image_size) + { + while(!m_send(response, sizeof(response))); + } + + m_dfu_state = ST_FW_VALID; +} + +/***************************************************************************** +* Public API +*****************************************************************************/ + +/* Initialize the state machine */ +void dfu_init (uint8_t *p_pipes) +{ + m_dfu_state = ST_IDLE; + memcpy(m_pipe_array, p_pipes, 3); +} + +/* Update the state machine according to the event in aci_evt */ +void dfu_update (aci_state_t *aci_state, aci_evt_t *aci_evt) +{ + const aci_rx_data_t *rx_data = &(aci_evt->params.data_received.rx_data); + uint8_t event = EV_ANY; + uint8_t pipe; + + RX_LED_TOGGLE(); + + m_aci_state = aci_state; + pipe = rx_data->pipe_number; + + // Incoming data packet + if (pipe == m_pipe_array[0]) { + event = DFU_PACKET_RX; + } + // Incoming control point + else if (pipe == m_pipe_array[2]) { + event = rx_data->aci_data[0]; + } + + // Update the state machine based on the incoming event and current state + switch (event) + { + // Receied data from data pipe + case DFU_PACKET_RX: + { + switch (m_dfu_state) + { + case ST_IDLE: + dfu_image_size_set(aci_evt); + break; + + case ST_RX_INIT_PKT: + dfu_init_pkt_handle(aci_evt); + break; + + case ST_RX_DATA_PKT: + dfu_data_pkt_handle(aci_evt); + break; + } + break; + } + + // Received op code from contro point pipe + /*case OP_CODE_START_DFU: + { + m_dfu_state = ST_IDLE; + break; + }*/ + + case OP_CODE_RECEIVE_INIT: + { + // Initial parameters + if (m_dfu_state == ST_RDY) + { + m_dfu_state = ST_RX_INIT_PKT; + } + break; + } + + case OP_CODE_RECEIVE_FW: + { + // Request receive firmware + if (m_dfu_state == ST_RDY || m_dfu_state == ST_RX_INIT_PKT) + { + m_dfu_state = ST_RX_DATA_PKT; + } + break; + } + + case OP_CODE_VALIDATE: + { + // Validate received firmware + if (m_dfu_state == ST_RX_DATA_PKT) + { + dfu_image_validate(aci_evt); + } + break; + } + + case OP_CODE_ACTIVATE_N_RESET: + { + // Active received firmware to run sketch + if (m_dfu_state == ST_FW_VALID) + { + dfu_image_activate(aci_evt); + } + break; + } + + case OP_CODE_SYS_RESET: + { + // Reset nRF8001 + while (!lib_aci_radio_reset(m_aci_state)); + m_dfu_state = ST_IDLE; + break; + } + + case OP_CODE_PKT_RCPT_NOTIF_REQ: + { + // Enable packet receipt + m_pkt_notif_target = + (uint16_t)aci_evt->params.data_received.rx_data.aci_data[2] << 8 | + (uint16_t)aci_evt->params.data_received.rx_data.aci_data[1]; + m_pkt_notif_target_cnt = m_pkt_notif_target; + break; + } + } +} diff --git a/Source/ble-caterina/BLE/dfu.h b/Source/ble-caterina/BLE/dfu.h new file mode 100644 index 0000000..2cc38fc --- /dev/null +++ b/Source/ble-caterina/BLE/dfu.h @@ -0,0 +1,69 @@ +/* Copyright (c) 2014, Nordic Semiconductor ASA + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef DFU_H_ +#define DFU_H_ + +#define ST_IDLE 1 +#define ST_RDY 2 +#define ST_RX_INIT_PKT 3 +#define ST_RX_DATA_PKT 4 +#define ST_FW_VALID 5 +#define ST_FW_INVALID 6 +#define ST_ANY 255 + +#define DFU_PACKET_RX 20 +#define EV_ANY 255 + +#define OP_CODE_START_DFU 1 /* 'Start DFU' */ +#define OP_CODE_RECEIVE_INIT 2 /* 'Initialize DFU parameters' */ +#define OP_CODE_RECEIVE_FW 3 /* 'Receive firmware image' */ +#define OP_CODE_VALIDATE 4 /* 'Validate firmware' */ +#define OP_CODE_ACTIVATE_N_RESET 5 /* 'Activate & Reset' */ +#define OP_CODE_SYS_RESET 6 /* 'Reset System' */ +#define OP_CODE_IMAGE_SIZE_REQ 7 /* 'Report received image size' .*/ +#define OP_CODE_PKT_RCPT_NOTIF_REQ 8 /* 'Request packet rcpt notification.*/ +#define OP_CODE_RESPONSE 16 /* 'Response.*/ +#define OP_CODE_PKT_RCPT_NOTIF 17 /* 'Packets Receipt Notification'.*/ + +/**@brief DFU Procedure type. + * + * @details This enumeration contains the types of DFU procedures. + */ +#define BLE_DFU_START_PROCEDURE 1 +#define BLE_DFU_INIT_PROCEDURE 2 +#define BLE_DFU_RECEIVE_APP_PROCEDURE 3 +#define BLE_DFU_VALIDATE_PROCEDURE 4 +#define BLE_DFU_PKT_RCPT_REQ_PROCEDURE 8 + +/**@brief DFU Response value type. + */ +#define BLE_DFU_RESP_VAL_SUCCESS 1 +#define BLE_DFU_RESP_VAL_INVALID_STATE 2 +#define BLE_DFU_RESP_VAL_NOT_SUPPORTED 3 +#define BLE_DFU_RESP_VAL_DATA_SIZE 4 +#define BLE_DFU_RESP_VAL_CRC_ERROR 5 +#define BLE_DFU_RESP_VAL_OPER_FAILED 6 + +void dfu_init (uint8_t *p_pipes); +void dfu_update (aci_state_t *aci_state, aci_evt_t *aci_evt); + +#endif /* DFU_H_ */ diff --git a/Source/ble-caterina/BLE/hal_aci_tl.c b/Source/ble-caterina/BLE/hal_aci_tl.c new file mode 100644 index 0000000..26272cf --- /dev/null +++ b/Source/ble-caterina/BLE/hal_aci_tl.c @@ -0,0 +1,234 @@ +/* Copyright (c) 2014, Nordic Semiconductor ASA + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include + +#include +#include "hal_aci_tl.h" +#include "hal_platform.h" + +static inline void m_aci_event_check (void); +static inline void m_aci_reqn_disable (void); +static inline void m_aci_reqn_enable (void); +static inline void m_spi_init (void); +static inline uint8_t m_spi_readwrite (const uint8_t aci_byte); +static inline void m_aci_spi_transfer (hal_aci_data_t * data_to_send, + hal_aci_data_t * received_data); + +uint8_t need_tx = 0; +uint8_t rx_ready = 0; + +static hal_aci_data_t data_to_send; +hal_aci_data_t received_data; + +static void m_aci_event_check(void) +{ + // nRF8001 has no event to send or isn't ready to received data + if (!hal_aci_tl_rdyn()) + { + // But we have data to send + if (need_tx) + { + // Pull the REQN to low + m_aci_reqn_enable(); + } + + return; + } + // nRF8001 is ready to received data or has event to send + else + { + if(!need_tx) + { + // No data to send, just read out event from nRF8001 when transmission begin + data_to_send.status_byte = 0; + data_to_send.buffer[0] = 0; + } + /* Receive and/or transmit data */ + m_aci_spi_transfer(&data_to_send, &received_data); + + need_tx = 0; + + /* Check if we received data */ + if (received_data.buffer[0] > 0) + { + rx_ready = 1; + } + } + + return; +} + +static inline void m_aci_reqn_disable (void) +{ + PORTD |= _BV(PD7); +} + +static inline void m_aci_reqn_enable (void) +{ + PORTD &= ~_BV(PD7); +} + +static void m_aci_spi_transfer (hal_aci_data_t * data_to_send, hal_aci_data_t * received_data) +{ + uint8_t byte_cnt; + uint8_t byte_sent_cnt; + uint8_t max_bytes; + + m_aci_reqn_enable(); + + /* Send length, receive header */ + byte_sent_cnt = 0; + received_data->status_byte = m_spi_readwrite(data_to_send->buffer[byte_sent_cnt++]); + /* Send first byte, receive length from slave */ + received_data->buffer[0] = m_spi_readwrite(data_to_send->buffer[byte_sent_cnt++]); + if (0 == data_to_send->buffer[0]) + { + max_bytes = received_data->buffer[0]; + } + else + { + /* Set the maximum to the biggest size. One command byte is already sent */ + max_bytes = (received_data->buffer[0] > (data_to_send->buffer[0] - 1)) + ? received_data->buffer[0] + : (data_to_send->buffer[0] - 1); + } + + if (max_bytes > HAL_ACI_MAX_LENGTH) + { + max_bytes = HAL_ACI_MAX_LENGTH; + } + + /* Transmit/receive the rest of the packet */ + for (byte_cnt = 0; byte_cnt < max_bytes; byte_cnt++) + { + received_data->buffer[byte_cnt+1] = m_spi_readwrite(data_to_send->buffer[byte_sent_cnt++]); + } + + /* RDYN should follow the REQN line in approx 100ns */ + m_aci_reqn_disable(); +} + +static void m_spi_init (void) +{ + /* Configure the IO lines */ + /* Set RDYN as input with pull-up */ + DDRE &= ~_BV(PE6); + PORTE |= _BV(PE6); + + /* Set REQN, MOSI & SCK as output */ + DDRB |= _BV(PB2) | _BV(PB1); + DDRD |= _BV(PD7); + PORTD |= _BV(PD7); + + /* Set MISO as input */ + DDRB &= ~_BV(PB3); + + // Set SS as output + DDRB |= _BV(PB0); + + /* Configure SPI registers */ + SPCR |= _BV(SPE) | _BV(DORD) | _BV(MSTR) | _BV(SPI2X) | _BV(SPR0); +} + +static uint8_t m_spi_readwrite(const uint8_t aci_byte) +{ + SPDR = aci_byte; + while(!(SPSR & (1<buffer[0]; + + if (length > HAL_ACI_MAX_LENGTH) + { + return false; + } + + if(need_tx) + { + return false; + } + + data_to_send.status_byte = 0; + memcpy((uint8_t *)&(data_to_send.buffer[0]), (uint8_t *)&p_aci_cmd->buffer[0], length + 1); + + need_tx = 1; + return true; +} + +bool hal_aci_tl_event_get(hal_aci_data_t *p_aci_data) +{ + if (!rx_ready) + { + m_aci_event_check(); + } + + if(rx_ready) + { + memcpy((uint8_t *)p_aci_data, (uint8_t *)&(received_data), sizeof(hal_aci_data_t)); + + rx_ready = 0; + + return true; + } + + return false; +} + +/* Returns true if the rdyn line is low */ +bool hal_aci_tl_rdyn (void) +{ + return !(PINE & _BV(PE6)); +} + +bool hal_aci_tl_event_peek(hal_aci_data_t *p_aci_data) +{ + m_aci_event_check(); + + if (rx_ready) + { + memcpy((uint8_t *)p_aci_data, (uint8_t *)&(received_data), sizeof(hal_aci_data_t)); + rx_ready = 0; + return true; + } + return false; +} diff --git a/Source/ble-caterina/BLE/hal_aci_tl.h b/Source/ble-caterina/BLE/hal_aci_tl.h new file mode 100644 index 0000000..0a0c0ac --- /dev/null +++ b/Source/ble-caterina/BLE/hal_aci_tl.h @@ -0,0 +1,125 @@ +/* Copyright (c) 2014, Nordic Semiconductor ASA + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/** @file + * @brief Interface for hal_aci_tl. + */ + +/** @defgroup hal_aci_tl hal_aci_tl +@{ +@ingroup hal + +@brief Module for the ACI Transport Layer interface +@details This module is responsible for sending and receiving messages over the +ACI interface of the nRF8001 chip. The hal_aci_tl_send_cmd() can be called +directly to send ACI commands. + + +The RDYN line is hooked to an interrupt on the MCU when the level is low. +The SPI master clocks in the interrupt context. +The ACI Command is taken from the head of the command queue is sent over the +SPI and the received ACI event is placed in the tail of the event queue. + +*/ + +#ifndef HAL_ACI_TL_H__ +#define HAL_ACI_TL_H__ + +#include + +#include "aci.h" + +#ifndef HAL_ACI_MAX_LENGTH +#define HAL_ACI_MAX_LENGTH 31 +#endif + +/************************************************************************/ +/* Unused nRF8001 pin */ +/************************************************************************/ +#define UNUSED 255 + +/** Data type for ACI commands and events */ +typedef struct { + uint8_t status_byte; + uint8_t buffer[HAL_ACI_MAX_LENGTH+1]; +} _aci_packed_ hal_aci_data_t; + +ACI_ASSERT_SIZE(hal_aci_data_t, HAL_ACI_MAX_LENGTH + 2); + +/** Datatype for ACI pins and interface (polling/interrupt)*/ +typedef struct aci_pins_t +{ + uint8_t board_name; + uint8_t reqn_pin; + uint8_t rdyn_pin; + uint8_t mosi_pin; + uint8_t miso_pin; + uint8_t sck_pin; + + uint8_t spi_clock_divider; + + uint8_t reset_pin; + uint8_t active_pin; + uint8_t optional_chip_sel_pin; + + bool interface_is_interrupt; + + uint8_t interrupt_number; +} aci_pins_t; + +/** @brief ACI Transport Layer initialization. + * @details + * This function initializes the transport layer, including configuring the + * SPI, creating message queues for Commands and Events and setting up + * interrupt if required. + * @param a_pins Pins on the MCU used to connect to the nRF8001 + * @param bool True if debug printing should be enabled on the Serial. + */ +void hal_aci_tl_init(void); + +/** @brief Sends an ACI command to the radio. + * @details + * This function sends an ACI command to the radio. This queue up the message + * to send and lower the request line. When the device lowers the ready line, + * @ref m_aci_spi_transfer() will send the data. + * @param aci_buffer Pointer to the message to send. + * @return True if the data was successfully queued for sending, + * false if there is no more space to store messages to send. + */ +bool hal_aci_tl_send(hal_aci_data_t *aci_buffer); + +/** @brief Get an ACI event from the event queue + * @details + * Call this function from the main context to get an event from the ACI event + * queue This is called by lib_aci_event_get + */ +bool hal_aci_tl_event_get(hal_aci_data_t *p_aci_data); + +/** @brief Get the state of the nRF8001 RDYN line + * @details + * True if rdyn is low, or false. + */ +bool hal_aci_tl_rdyn (void); + +bool hal_aci_tl_event_peek(hal_aci_data_t *p_aci_data); + +#endif /* HAL_ACI_TL_H__ */ +/** @} */ diff --git a/Source/ble-caterina/BLE/hal_platform.h b/Source/ble-caterina/BLE/hal_platform.h new file mode 100644 index 0000000..4dad68b --- /dev/null +++ b/Source/ble-caterina/BLE/hal_platform.h @@ -0,0 +1,37 @@ +/* Copyright (c) 2014, Nordic Semiconductor ASA + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef PLATFORM_H__ +#define PLATFORM_H__ + +/** @file +* @brief +*/ + +//Board dependent defines + //For Arduino this AVR specific library has to be used for reading from Flash memory + #include + #ifdef PROGMEM + #undef PROGMEM + #define PROGMEM __attribute__(( section(".progmem.data") )) + #endif + +#endif /* PLATFORM_H__ */ diff --git a/Source/ble-caterina/BLE/lib_aci.c b/Source/ble-caterina/BLE/lib_aci.c new file mode 100644 index 0000000..2fc76fb --- /dev/null +++ b/Source/ble-caterina/BLE/lib_aci.c @@ -0,0 +1,293 @@ +/* Copyright (c) 2014, Nordic Semiconductor ASA + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/** @file + @brief Implementation of the ACI library. + */ + +#include +#include +#include +#include + +#include "hal_platform.h" +#include "aci.h" +#include "aci_cmds.h" +#include "aci_evts.h" +#include "aci_protocol_defines.h" +#include "acilib.h" +#include "acilib_defs.h" +#include "acilib_if.h" +#include "hal_aci_tl.h" +#include "lib_aci.h" + +#define LIB_ACI_DEFAULT_CREDIT_NUMBER 1 + +extern uint8_t need_tx; +extern uint8_t rx_ready; + +extern hal_aci_data_t received_data; + +/* +Global additionally used used in aci_setup +*/ + +//bool lib_aci_is_pipe_available(aci_state_t *aci_stat, uint8_t pipe) +//{ +// uint8_t byte_idx; +// +// byte_idx = pipe / 8; +// if (aci_stat->pipes_open_bitmap[byte_idx] & (0x01 << (pipe % 8))) +// { +// return(true); +// } +// return(false); +//} + +bool lib_aci_radio_reset(aci_state_t *aci_stat) +{ + hal_aci_data_t msg_to_send; + uint8_t *buffer = &(msg_to_send.buffer[0]); + + *(buffer + OFFSET_ACI_CMD_T_LEN) = MSG_BASEBAND_RESET_LEN; + *(buffer + OFFSET_ACI_CMD_T_CMD_OPCODE) = ACI_CMD_RADIO_RESET; + + return hal_aci_tl_send(&msg_to_send); +} + +void lib_aci_init(aci_state_t *aci_stat) +{ + uint8_t i; + + for (i = 0; i < PIPES_ARRAY_SIZE; i++) + { + aci_stat->pipes_open_bitmap[i] = 0; + aci_stat->pipes_closed_bitmap[i] = 0; + } + + hal_aci_tl_init(); + + /* If RDYN is not low, there is no message pending on the nrF8001, at which + * point we should performa a radio reset to get in a known state. + */ + //if (!hal_aci_tl_rdyn()) + //{ + hal_aci_evt_t aci_data; + + lib_aci_radio_reset(aci_stat); + + while (1) + { + //Wait for the command response of the radio reset command. + //as the nRF8001 will be in either SETUP or STANDBY after the ACI Reset Radio is processe + if (true == lib_aci_event_get(aci_stat, &aci_data)) + { + aci_evt_t * aci_evt; + aci_evt = &(aci_data.evt); + + if (ACI_EVT_CMD_RSP == aci_evt->evt_opcode) + { + hal_aci_data_t received_msg; + + //Inject a Device Started Event Setup to the ACI Event Queue + received_msg.status_byte = 0; + received_msg.buffer[0] = 4; //Length + received_msg.buffer[1] = 0x81; //Device Started Event + //if (ACI_STATUS_ERROR_DEVICE_STATE_INVALID == aci_evt->params.cmd_rsp.cmd_status || ACI_STATUS_SUCCESS == aci_evt->params.cmd_rsp.cmd_status) //in SETUP + //{ + received_msg.buffer[2] = 0x02; //Setup + //} + //else if () //We are now in STANDBY + //{ + // received_msg.buffer[2] = 0x03; //Standby + //} + received_msg.buffer[3] = 0; //Hardware Error -> None + received_msg.buffer[4] = 2; //Data Credit Available + + memcpy((uint8_t *)&(received_data), (uint8_t *)&(received_msg), sizeof(hal_aci_data_t)); + rx_ready = 1; + //Break out of the while loop + break; + } + } + } + //} +} + +bool lib_aci_connect(uint16_t run_timeout, uint16_t adv_interval) +{ + hal_aci_data_t msg_to_send; + aci_cmd_params_connect_t aci_cmd_params_connect; + + uint8_t *buffer = &(msg_to_send.buffer[0]); + + aci_cmd_params_connect.timeout = run_timeout; + aci_cmd_params_connect.adv_interval = adv_interval; + + *(buffer + OFFSET_ACI_CMD_T_LEN) = MSG_CONNECT_LEN; + *(buffer + OFFSET_ACI_CMD_T_CMD_OPCODE) = ACI_CMD_CONNECT; + + *(buffer + OFFSET_ACI_CMD_T_CONNECT + + OFFSET_ACI_CMD_PARAMS_CONNECT_T_TIMEOUT_MSB) = + (uint8_t)(aci_cmd_params_connect.timeout >> 8); + + *(buffer + OFFSET_ACI_CMD_T_CONNECT + + OFFSET_ACI_CMD_PARAMS_CONNECT_T_TIMEOUT_LSB) = + (uint8_t)(aci_cmd_params_connect.timeout); + + *(buffer + OFFSET_ACI_CMD_T_CONNECT + + OFFSET_ACI_CMD_PARAMS_CONNECT_T_ADV_INTERVAL_MSB) = + (uint8_t)(aci_cmd_params_connect.adv_interval >> 8); + + *(buffer + OFFSET_ACI_CMD_T_CONNECT + + OFFSET_ACI_CMD_PARAMS_CONNECT_T_ADV_INTERVAL_LSB) = + (uint8_t)(aci_cmd_params_connect.adv_interval); + + return hal_aci_tl_send(&msg_to_send); +} + +bool lib_aci_disconnect(aci_state_t *aci_stat, aci_disconnect_reason_t reason) +{ + bool ret_val; + uint8_t i; + hal_aci_data_t msg_to_send; + uint8_t *buffer = &(msg_to_send.buffer[0]); + + aci_cmd_params_disconnect_t aci_cmd_params_disconnect; + aci_cmd_params_disconnect.reason = reason; + + *(buffer + OFFSET_ACI_CMD_T_LEN) = MSG_DISCONNECT_LEN; + *(buffer + OFFSET_ACI_CMD_T_CMD_OPCODE) = ACI_CMD_DISCONNECT; + + *(buffer + OFFSET_ACI_CMD_T_DISCONNECT + + OFFSET_ACI_CMD_PARAMS_DISCONNECT_T_REASON) = + (uint8_t)(aci_cmd_params_disconnect.reason); + + ret_val = hal_aci_tl_send(&msg_to_send); + /* If we have actually sent the disconnect */ + if (ret_val) + { + /* Update pipes immediately so that while the disconnect is happening, + * the application can't attempt sending another message + * If the application sends another message before we updated this + * a ACI Pipe Error Event will be received from nRF8001 + */ + for (i=0; i < PIPES_ARRAY_SIZE; i++) + { + aci_stat->pipes_open_bitmap[i] = 0; + aci_stat->pipes_closed_bitmap[i] = 0; + } + } + return ret_val; +} + +bool lib_aci_send_data(uint8_t pipe, uint8_t *p_value, uint8_t size) +{ + aci_cmd_params_send_data_t aci_cmd_params_send_data; + hal_aci_data_t msg_to_send; + uint8_t *buffer = &(msg_to_send.buffer[0]); + + aci_cmd_params_send_data.tx_data.pipe_number = pipe; + memcpy(&(aci_cmd_params_send_data.tx_data.aci_data[0]), p_value, size); + + *(buffer + OFFSET_ACI_CMD_T_LEN) = MSG_SEND_DATA_BASE_LEN + size; + *(buffer + OFFSET_ACI_CMD_T_CMD_OPCODE) = ACI_CMD_SEND_DATA; + + *(buffer + OFFSET_ACI_CMD_T_SEND_DATA + + OFFSET_ACI_CMD_PARAMS_SEND_DATA_T_TX_DATA + + OFFSET_ACI_TX_DATA_T_PIPE_NUMBER) = + aci_cmd_params_send_data.tx_data.pipe_number; + + memcpy((buffer + OFFSET_ACI_CMD_T_SEND_DATA + + OFFSET_ACI_CMD_PARAMS_SEND_DATA_T_TX_DATA + + OFFSET_ACI_TX_DATA_T_ACI_DATA), + &(aci_cmd_params_send_data.tx_data.aci_data[0]), size); + + return hal_aci_tl_send(&msg_to_send); +} + +bool lib_aci_event_get(aci_state_t *aci_stat, hal_aci_evt_t *p_aci_evt_data) +{ + bool status = false; + + status = hal_aci_tl_event_get((hal_aci_data_t *)p_aci_evt_data); + + /** + Update the state of the ACI with the + ACI Events -> Pipe Status, Disconnected, Connected, Bond Status, Pipe Error + */ + if (true == status) + { + aci_evt_t * aci_evt; + + aci_evt = &p_aci_evt_data->evt; + + switch(aci_evt->evt_opcode) + { + case ACI_EVT_PIPE_STATUS: + { + uint8_t i=0; + + for (i=0; i < PIPES_ARRAY_SIZE; i++) + { + aci_stat->pipes_open_bitmap[i] = aci_evt->params.pipe_status.pipes_open_bitmap[i]; + aci_stat->pipes_closed_bitmap[i] = aci_evt->params.pipe_status.pipes_closed_bitmap[i]; + } + } + break; + + case ACI_EVT_DISCONNECTED: + { + uint8_t i=0; + + for (i=0; i < PIPES_ARRAY_SIZE; i++) + { + aci_stat->pipes_open_bitmap[i] = 0; + aci_stat->pipes_closed_bitmap[i] = 0; + } + aci_stat->confirmation_pending = false; + aci_stat->data_credit_available = aci_stat->data_credit_total; + + } + break; + + case ACI_EVT_TIMING: + aci_stat->connection_interval = aci_evt->params.timing.conn_rf_interval; + aci_stat->slave_latency = aci_evt->params.timing.conn_slave_rf_latency; + aci_stat->supervision_timeout = aci_evt->params.timing.conn_rf_timeout; + break; + + default: + /* Need default case to avoid compiler warnings about missing enum + * values on some platforms. + */ + break; + } + } + + return status; +} + +bool lib_aci_event_peek(hal_aci_evt_t *p_aci_evt_data) +{ + return hal_aci_tl_event_peek((hal_aci_data_t *)p_aci_evt_data); +} + diff --git a/Source/ble-caterina/BLE/lib_aci.h b/Source/ble-caterina/BLE/lib_aci.h new file mode 100644 index 0000000..c4fbe9e --- /dev/null +++ b/Source/ble-caterina/BLE/lib_aci.h @@ -0,0 +1,220 @@ +/* Copyright (c) 2014, Nordic Semiconductor ASA + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef LIB_ACI_H__ +#define LIB_ACI_H__ + +/** @file +* @brief ACI library +*/ + +/** @addtogroup lib_aci +@{ +@brief Library for the logical part of the Application Controller Interface (ACI) +*/ + +#include + +#include "hal_platform.h" +#include "hal_aci_tl.h" +#include "aci.h" +#include "aci_cmds.h" +#include "aci_evts.h" + + +#define EVT_CMD_RESPONSE_MIN_LENGTH 3 + +#define PIPES_ARRAY_SIZE ((ACI_DEVICE_MAX_PIPES + 7)/8) + +/* Same size as a hal_aci_data_t */ +typedef struct { + uint8_t debug_byte; + aci_evt_t evt; +} _aci_packed_ hal_aci_evt_t; + +ACI_ASSERT_SIZE(hal_aci_evt_t, 34); + +typedef struct +{ + uint8_t location; /**< enum aci_pipe_store_t */ + aci_pipe_type_t pipe_type; +} services_pipe_type_mapping_t; + +typedef struct aci_setup_info_t +{ + services_pipe_type_mapping_t *services_pipe_type_mapping; + uint8_t number_of_pipes; + hal_aci_data_t *setup_msgs; + uint8_t num_setup_msgs; +} aci_setup_info_t; + +typedef struct aci_state_t +{ + /* Pins on the MCU used to connect to the nRF8001 */ + aci_pins_t aci_pins; + + /* Data structures that are created from nRFgo Studio */ + aci_setup_info_t aci_setup_info; + + /* ( aci_bond_status_code_t ) Is the nRF8001 bonded to a peer device */ + uint8_t bonded; + + /* Total data credit available for the specific version of the nRF8001, total + * equals available when a link is established + */ + uint8_t data_credit_total; + + /* Operating mode of the nRF8001 */ + aci_device_operation_mode_t device_state; + + /* Start : Variables that are valid only when in a connection */ + + /* Available data credits at a specific point of time, ACI_EVT_DATA_CREDIT + * updates the available credits */ + uint8_t data_credit_available; + + /* Multiply by 1.25 to get the connection interval in milliseconds*/ + uint16_t connection_interval; + + /* Number of consecutive connection intervals that the nRF8001 is not + * required to transmit. Use this to save power + */ + uint16_t slave_latency; + + /* Multiply by 10 to get the supervision timeout in milliseconds */ + uint16_t supervision_timeout; + + /* Bitmap -> pipes are open and can be used for sending data over the air */ + uint8_t pipes_open_bitmap[PIPES_ARRAY_SIZE]; + + /* Bitmap -> pipes are closed and cannot be used for sending data over the + * air + */ + uint8_t pipes_closed_bitmap[PIPES_ARRAY_SIZE]; + + /* Attribute protocol Handle Value confirmation is pending for a Handle Value + * Indication (ACK is pending for a TX_ACK pipe) on local GATT Server + */ + bool confirmation_pending; + + /* End : Variables that are valid only when in a connection */ +} aci_state_t; + + + +#define DISCONNECT_REASON_CX_TIMEOUT 0x08 +#define DISCONNECT_REASON_CX_CLOSED_BY_PEER_DEVICE 0x13 +#define DISCONNECT_REASON_POWER_LOSS 0x14 +#define DISCONNECT_REASON_CX_CLOSED_BY_LOCAL_DEVICE 0x16 +#define DISCONNECT_REASON_ADVERTISER_TIMEOUT 0x50 + + +/** @name Functions for library management */ +/* @{ */ + +/** @brief Initialization function. + * @details This function shall be used to initialize/reset ACI Library and + * also Resets the nRF8001 by togging the reset pin of the nRF8001. This + * function will reset all the variables locally used by ACI library to + * their respective default values. + * @param bool True if the data was successfully queued for sending, + * false if there is no more space to store messages to send. + */ +void lib_aci_init(aci_state_t *aci_stat); + +/** @brief Checks if a given pipe is available. + * @param pipe Pipe to check. + * @return True if the pipe is available, otherwise false. + */ +//bool lib_aci_is_pipe_available(aci_state_t *aci_stat, uint8_t pipe); + +/* @} */ + +/** @name ACI Commands available in all modes */ +//@{ + +/** @brief Resets the radio. + * @details The function sends a @c BasebandReset command to the radio. + * @return True if the transaction is successfully initiated. + */ +bool lib_aci_radio_reset(aci_state_t *aci_stat); + +/* @} */ + +/** @name ACI commands available in Active mode */ +/* @{ */ + +/** @brief Tries to connect to a peer device. + * @details This function sends a @c Connect command to the radio. + * @param run_timeout Maximum advertising time in seconds (0 means infinite). + * @param adv_interval Advertising interval (in multiple of 0.625 ms). + * @return True if the transaction is successfully initiated. + */ +bool lib_aci_connect(uint16_t run_timeout, uint16_t adv_interval); + +/** @brief Disconnects from peer device. + * @details This function sends a @c Disconnect command to the radio. + * @param reason Reason for disconnecting. + * @return True if the transaction is successfully initiated. + */ +bool lib_aci_disconnect(aci_state_t *aci_stat, aci_disconnect_reason_t reason); + +/* @} */ + +/** @name ACI commands available in Connected mode */ +/* @{ */ + +/** @brief Sends data on a given pipe. + * @details This function sends a @c SendData command with application data to + * the radio. This function memorizes credit use, and checks that + * enough credits are available. + * @param pipe Pipe number on which the data should be sent. + * @param value Pointer to the data to send. + * @param size Size of the data to send. + * @return True if the transaction is successfully initiated. + */ +bool lib_aci_send_data(uint8_t pipe, uint8_t *value, uint8_t size); + +/* @} */ + +/** @name ACI commands available while connected in Bond mode */ +/* @{ */ + +/* @} */ + +/** @brief Gets an ACI event from the ACI Event Queue + * @details This function gets an ACI event from the ACI event queue. The + * queue is updated by the SPI driver for the ACI running in the interrupt + * context + * @param aci_stat pointer to the state of the ACI. + * @param p_aci_data pointer to the ACI Event. The ACI Event received will be + * copied into this pointer. + * @return True if an ACI Event was copied to the pointer. +*/ +bool lib_aci_event_get(aci_state_t *aci_stat, hal_aci_evt_t * aci_evt); + +/* @} */ + +/* @} */ + +bool lib_aci_event_peek(hal_aci_evt_t *p_aci_evt_data); + +#endif /* LIB_ACI_H__ */ diff --git a/Source/ble-caterina/BLE/services.h b/Source/ble-caterina/BLE/services.h new file mode 100644 index 0000000..7ffdff3 --- /dev/null +++ b/Source/ble-caterina/BLE/services.h @@ -0,0 +1,176 @@ +/** +* This file is autogenerated by nRFgo Studio 1.17.0.3211 +*/ + +#ifndef SETUP_MESSAGES_H__ +#define SETUP_MESSAGES_H__ + +#include "hal_platform.h" +#include "aci.h" + + +#define SETUP_ID 0 +#define SETUP_FORMAT 3 /** nRF8001 D */ +#define ACI_DYNAMIC_DATA_SIZE 171 + +/* Service: GATT - Characteristic: Service Changed - Pipe: TX_ACK */ +#define PIPE_GATT_SERVICE_CHANGED_TX_ACK 1 +#define PIPE_GATT_SERVICE_CHANGED_TX_ACK_MAX_SIZE 4 + +/* Service: Device Firmware Update BLE Service - Characteristic: DFU Packet - Pipe: RX */ +#define PIPE_DEVICE_FIRMWARE_UPDATE_BLE_SERVICE_DFU_PACKET_RX 2 +#define PIPE_DEVICE_FIRMWARE_UPDATE_BLE_SERVICE_DFU_PACKET_RX_MAX_SIZE 20 + +/* Service: Device Firmware Update BLE Service - Characteristic: DFU Control Point - Pipe: TX */ +#define PIPE_DEVICE_FIRMWARE_UPDATE_BLE_SERVICE_DFU_CONTROL_POINT_TX 3 +#define PIPE_DEVICE_FIRMWARE_UPDATE_BLE_SERVICE_DFU_CONTROL_POINT_TX_MAX_SIZE 20 + +/* Service: Device Firmware Update BLE Service - Characteristic: DFU Control Point - Pipe: RX_ACK_AUTO */ +#define PIPE_DEVICE_FIRMWARE_UPDATE_BLE_SERVICE_DFU_CONTROL_POINT_RX_ACK_AUTO 4 +#define PIPE_DEVICE_FIRMWARE_UPDATE_BLE_SERVICE_DFU_CONTROL_POINT_RX_ACK_AUTO_MAX_SIZE 20 + + +#define NUMBER_OF_PIPES 4 + +#define SERVICES_PIPE_TYPE_MAPPING_CONTENT {\ + {ACI_STORE_LOCAL, ACI_TX_ACK}, \ + {ACI_STORE_LOCAL, ACI_RX}, \ + {ACI_STORE_LOCAL, ACI_TX}, \ + {ACI_STORE_LOCAL, ACI_RX_ACK_AUTO}, \ +} + +#define GAP_PPCP_MAX_CONN_INT 0x12 /**< Maximum connection interval as a multiple of 1.25 msec , 0xFFFF means no specific value requested */ +#define GAP_PPCP_MIN_CONN_INT 0xa /**< Minimum connection interval as a multiple of 1.25 msec , 0xFFFF means no specific value requested */ +#define GAP_PPCP_SLAVE_LATENCY 0 +#define GAP_PPCP_CONN_TIMEOUT 0xa /** Connection Supervision timeout multiplier as a multiple of 10msec, 0xFFFF means no specific value requested */ + +#define NB_SETUP_MESSAGES 22 +#define SETUP_MESSAGES_CONTENT {\ + {0x00,\ + {\ + 0x07,0x06,0x00,0x00,0x03,0x02,0x42,0x07,\ + },\ + },\ + {0x00,\ + {\ + 0x1f,0x06,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x04,0x01,0x01,0x00,0x00,0x06,0x00,0x00,\ + 0xd0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x15,\ + },\ + },\ + {0x00,\ + {\ + 0x1f,0x06,0x10,0x1c,0x30,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ + 0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x14,0x03,0x90,0x01,0xff,\ + },\ + },\ + {0x00,\ + {\ + 0x1f,0x06,0x10,0x38,0xff,0xff,0x02,0x58,0x0a,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ + 0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ + },\ + },\ + {0x00,\ + {\ + 0x05,0x06,0x10,0x54,0x00,0x00,\ + },\ + },\ + {0x00,\ + {\ + 0x1f,0x06,0x20,0x00,0x04,0x04,0x02,0x02,0x00,0x01,0x28,0x00,0x01,0x00,0x18,0x04,0x04,0x05,0x05,0x00,\ + 0x02,0x28,0x03,0x01,0x02,0x03,0x00,0x00,0x2a,0x04,0x04,0x14,\ + },\ + },\ + {0x00,\ + {\ + 0x1f,0x06,0x20,0x1c,0x03,0x00,0x03,0x2a,0x00,0x01,0x44,0x46,0x55,0x64,0x69,0x63,0x73,0x65,0x6d,0x69,\ + 0x2e,0x63,0x6f,0x6d,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x04,\ + },\ + },\ + {0x00,\ + {\ + 0x1f,0x06,0x20,0x38,0x05,0x05,0x00,0x04,0x28,0x03,0x01,0x02,0x05,0x00,0x01,0x2a,0x06,0x04,0x03,0x02,\ + 0x00,0x05,0x2a,0x01,0x01,0x80,0x00,0x04,0x04,0x05,0x05,0x00,\ + },\ + },\ + {0x00,\ + {\ + 0x1f,0x06,0x20,0x54,0x06,0x28,0x03,0x01,0x02,0x07,0x00,0x04,0x2a,0x06,0x04,0x09,0x08,0x00,0x07,0x2a,\ + 0x04,0x01,0x0a,0x00,0x12,0x00,0x00,0x00,0x0a,0x00,0x04,0x04,\ + },\ + },\ + {0x00,\ + {\ + 0x1f,0x06,0x20,0x70,0x02,0x02,0x00,0x08,0x28,0x00,0x01,0x01,0x18,0x04,0x04,0x05,0x05,0x00,0x09,0x28,\ + 0x03,0x01,0x22,0x0a,0x00,0x05,0x2a,0x26,0x04,0x05,0x04,0x00,\ + },\ + },\ + {0x00,\ + {\ + 0x1f,0x06,0x20,0x8c,0x0a,0x2a,0x05,0x01,0x00,0x00,0x00,0x00,0x46,0x14,0x03,0x02,0x00,0x0b,0x29,0x02,\ + 0x01,0x00,0x00,0x04,0x04,0x10,0x10,0x00,0x0c,0x28,0x00,0x01,\ + },\ + },\ + {0x00,\ + {\ + 0x1f,0x06,0x20,0xa8,0x23,0xd1,0xbc,0xea,0x5f,0x78,0x23,0x15,0xde,0xef,0x12,0x12,0x30,0x15,0x00,0x00,\ + 0x04,0x04,0x13,0x13,0x00,0x0d,0x28,0x03,0x01,0x04,0x0e,0x00,\ + },\ + },\ + {0x00,\ + {\ + 0x1f,0x06,0x20,0xc4,0x23,0xd1,0xbc,0xea,0x5f,0x78,0x23,0x15,0xde,0xef,0x12,0x12,0x32,0x15,0x00,0x00,\ + 0x44,0x10,0x14,0x00,0x00,0x0e,0x15,0x32,0x02,0x00,0x00,0x00,\ + },\ + },\ + {0x00,\ + {\ + 0x1f,0x06,0x20,0xe0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ + 0x00,0x04,0x04,0x13,0x13,0x00,0x0f,0x28,0x03,0x01,0x18,0x10,\ + },\ + },\ + {0x00,\ + {\ + 0x1f,0x06,0x20,0xfc,0x00,0x23,0xd1,0xbc,0xea,0x5f,0x78,0x23,0x15,0xde,0xef,0x12,0x12,0x31,0x15,0x00,\ + 0x00,0x54,0x10,0x14,0x00,0x00,0x10,0x15,0x31,0x02,0x00,0x00,\ + },\ + },\ + {0x00,\ + {\ + 0x1f,0x06,0x21,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ + 0x00,0x00,0x46,0x14,0x03,0x02,0x00,0x11,0x29,0x02,0x01,0x00,\ + },\ + },\ + {0x00,\ + {\ + 0x05,0x06,0x21,0x34,0x00,0x00,\ + },\ + },\ + {0x00,\ + {\ + 0x1f,0x06,0x40,0x00,0x2a,0x05,0x01,0x00,0x04,0x04,0x00,0x0a,0x00,0x0b,0x15,0x32,0x02,0x00,0x08,0x04,\ + 0x00,0x0e,0x00,0x00,0x15,0x31,0x02,0x04,0x02,0x04,0x00,0x10,\ + },\ + },\ + {0x00,\ + {\ + 0x05,0x06,0x40,0x1c,0x00,0x11,\ + },\ + },\ + {0x00,\ + {\ + 0x13,0x06,0x50,0x00,0x23,0xd1,0xbc,0xea,0x5f,0x78,0x23,0x15,0xde,0xef,0x12,0x12,0x00,0x00,0x00,0x00,\ + },\ + },\ + {0x00,\ + {\ + 0x0c,0x06,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ + },\ + },\ + {0x00,\ + {\ + 0x06,0x06,0xf0,0x00,0x03,0x77,0x24,\ + },\ + },\ +} + +#endif diff --git a/Source/ble-caterina/Caterina.c b/Source/ble-caterina/Caterina.c new file mode 100644 index 0000000..d4a8f26 --- /dev/null +++ b/Source/ble-caterina/Caterina.c @@ -0,0 +1,310 @@ + + +#define INCLUDE_FROM_CATERINA_C +#include "Caterina.h" + +#include "BLE/lib_aci.h" +#include "BLE/aci_evts.h" +#include "BLE/dfu.h" +#include "BLE/services.h" +#include "BLE/aci_setup.h" +#include + +static struct aci_state_t aci_state; +uint8_t pipes[3] = {PIPE_DEVICE_FIRMWARE_UPDATE_BLE_SERVICE_DFU_PACKET_RX, PIPE_DEVICE_FIRMWARE_UPDATE_BLE_SERVICE_DFU_CONTROL_POINT_TX, PIPE_DEVICE_FIRMWARE_UPDATE_BLE_SERVICE_DFU_CONTROL_POINT_RX_ACK_AUTO}; +uint16_t conn_timeout = 180; +uint16_t conn_interval = 0x0050; + +//static services_pipe_type_mapping_t services_pipe_type_mapping[NUMBER_OF_PIPES] = SERVICES_PIPE_TYPE_MAPPING_CONTENT; +static hal_aci_data_t setup_msgs[NB_SETUP_MESSAGES] PROGMEM = SETUP_MESSAGES_CONTENT; + +/** Flag to indicate if the bootloader should be running, or should exit and allow the application code to run + * via a watchdog reset. When cleared the bootloader will exit, starting the watchdog and entering an infinite + * loop until the AVR restarts and the application runs. + */ +bool RunBootloader = true; + +/* Pulse generation counters to keep track of the time remaining for each pulse type */ +#define TX_RX_LED_PULSE_PERIOD 100 +uint16_t TxLEDPulse = 0; // time remaining for Tx LED pulse +uint16_t RxLEDPulse = 0; // time remaining for Rx LED pulse + +/* Bootloader timeout timer */ +#define TIMEOUT_PERIOD 8000//4000 +uint16_t Timeout = 0; + +uint16_t bootKey = 0x7777; +volatile uint16_t *const bootKeyPtr = (volatile uint16_t *)0x0800; + +void StartSketch(void) +{ + CPU_PRESCALE(1); + + cli(); + + /* Undo TIMER1 setup and clear the count before running the sketch */ + TIMSK1 = 0; + TCCR1B = 0; + TCNT1H = 0; // 16-bit write to TCNT1 requires high byte be written first + TCNT1L = 0; + + /* Relocate the interrupt vector table to the application section */ + MCUCR = (1 << IVCE); + MCUCR = 0; + + L_LED_OFF(); + //TX_LED_OFF(); + //RX_LED_OFF(); + + /* jump to beginning of application space */ + __asm__ volatile("jmp 0x0000"); +} + +/* Breathing animation on L LED indicates bootloader is running */ +uint16_t LLEDPulse; +void LEDPulse(void) +{ + LLEDPulse+=2; + uint8_t p = LLEDPulse >> 8; + if (p > 127) + p = 254-p; + p += p; + if (((uint8_t)LLEDPulse) > p) + L_LED_OFF(); + else + L_LED_ON(); +} + +/** Main program entry point. This routine configures the hardware required by the bootloader, then continuously + * runs the bootloader processing routine until it times out or is instructed to exit. + */ +int main(void) +{ + //DDRB |= _BV(PB4); PORTB |= _BV(PB4); PORTB &= ~_BV(PB4); // For debugging + + // Save the value of the boot key memory before it is overwritten + uint16_t bootKeyPtrVal = *bootKeyPtr; + *bootKeyPtr = 0; + + // Check the reason for the reset so we can act accordingly + uint8_t mcusr_state = MCUSR; // store the initial state of the Status register + MCUSR = 0; // clear all reset flags + + // Watchdog may be configured with a 15 ms period so must disable it before going any further + wdt_disable(); + + /*if (mcusr_state & (1< TIMEOUT_PERIOD) + { + RunBootloader = false; + } + + ble_Task(pipes); + + LEDPulse(); + } + + // Jump to beginning of application space to run the sketch - do not reset + StartSketch(); +} + +/** Configures all hardware required for the bootloader. */ +void SetupHardware(void) +{ + /* Disable watchdog if enabled by bootloader/fuses */ + //MCUSR &= ~(1 << WDRF); + //wdt_disable(); + + /* Disable clock division */ + clock_prescale_set(clock_div_2); + + /* Relocate the interrupt vector table to the bootloader section */ + MCUCR = (1 << IVCE); + MCUCR = (1 << IVSEL); + + LED_SETUP(); + CPU_PRESCALE(1); //If 0, 1ms timer ISR, if 1, 2ms timer ISR. + //L_LED_OFF(); + TX_LED_OFF(); + RX_LED_OFF(); + + /* Initialize TIMER1 to handle bootloader timeout and LED tasks. + * With 16 MHz clock and 1/64 prescaler, timer 1 is clocked at 250 kHz + * Our chosen compare match generates an interrupt every 1 ms. + * This interrupt is disabled selectively when doing memory reading, erasing, + * or writing since SPM has tight timing requirements. + */ + OCR1AH = 0; + OCR1AL = 250; + TIMSK1 = (1 << OCIE1A); // enable timer 1 output compare A match interrupt + TCCR1B = ((1 << CS11) | (1 << CS10)); // 1/64 prescaler on timer 1 input +} + +//uint16_t ctr = 0; +ISR(TIMER1_COMPA_vect, ISR_BLOCK) +{ + /* Reset counter */ + TCNT1H = 0; + TCNT1L = 0; + + if (pgm_read_word(0) != 0xFFFF) + Timeout++; +} + +/* Get and process events from the BLE link. If we detect an event indicating + * that we are about to receive a new firmware image on BLE we set "ble_mode" + * to a true value. + */ + +void ble_Task(uint8_t *pipes) +{ + hal_aci_evt_t aci_data; + aci_evt_t *aci_evt; + uint8_t pipe; + static bool setup_required = 0; + + // Attempt to grab an event from the BLE message queue + if (!lib_aci_event_get(&aci_state, &aci_data)) { + return; + } + + aci_evt = &(aci_data.evt); + + switch(aci_evt->evt_opcode) + { + case ACI_EVT_DEVICE_STARTED: + + aci_state.data_credit_total = aci_evt->params.device_started.credit_available; + + if(aci_evt->params.device_started.device_mode == ACI_DEVICE_SETUP) + { + setup_required = 1; + + } + else if (aci_evt->params.device_started.device_mode == ACI_DEVICE_STANDBY) + { + //if (aci_evt->params.device_started.hw_error) { + //Magic number used to make sure the HW error event is handled correctly. + // _delay_ms (20); + //} + //else { + lib_aci_connect (conn_timeout, conn_interval); + //} + } + break; // ACI Device Started Event + + case ACI_EVT_CMD_RSP: + if (aci_evt->params.cmd_rsp.cmd_opcode == ACI_CMD_RADIO_RESET) + { + if (aci_evt->params.cmd_rsp.cmd_status == ACI_STATUS_SUCCESS) + { + lib_aci_connect (conn_timeout, conn_interval); + } + } + break; // ACI Command Response + + case ACI_EVT_CONNECTED: + Timeout = 0; + // We should have checked that this is true before we jumped into + // the bootloader. Hopefully we did. + + aci_state.data_credit_available = aci_state.data_credit_total; + break; + + case ACI_EVT_DATA_CREDIT: + Timeout = 0; + aci_state.data_credit_available = aci_state.data_credit_available + + aci_evt->params.data_credit.credit; + break; + + case ACI_EVT_PIPE_ERROR: + Timeout = 0; + // If we received a pipe error, some message got borked. + // All we can do is update our credit to reflect it + + if (aci_evt->params.pipe_error.error_code != ACI_STATUS_ERROR_PEER_ATT_ERROR) + { + aci_state.data_credit_available++; + } + break; + + case ACI_EVT_DATA_RECEIVED: + Timeout = 0; + // If data received is on either of the DFU pipes, we enter DFU mode. + // We then update the DFU state machine to run the transfer. + + pipe = aci_evt->params.data_received.rx_data.pipe_number; + if (pipe == pipes[0] || pipe == pipes[2]) + { + dfu_update(&aci_state, aci_evt); + } + break; + + case ACI_EVT_DISCONNECTED: + lib_aci_connect (conn_timeout, conn_interval); + break; + + case ACI_EVT_HW_ERROR: + lib_aci_connect (conn_timeout, conn_interval); + break; + + default: + break; + } + + if(setup_required == 1) + { + if (SETUP_SUCCESS == do_aci_setup(&aci_state)) + { + setup_required = 0; + } + } + + return; +} + + diff --git a/Source/ble-caterina/Caterina.h b/Source/ble-caterina/Caterina.h new file mode 100644 index 0000000..cae214e --- /dev/null +++ b/Source/ble-caterina/Caterina.h @@ -0,0 +1,90 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2011. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * + * Header file for BootloaderCDC.c. + */ + +#ifndef _CDC_H_ +#define _CDC_H_ + + /* Includes: */ + #include + #include + #include + #include + #include + #include + #include + + #include "Descriptors.h" + + /* Macros: */ + /** Version major of the CDC bootloader. */ + #define BOOTLOADER_VERSION_MAJOR 0x01 + + /** Version minor of the CDC bootloader. */ + #define BOOTLOADER_VERSION_MINOR 0x00 + + /** Hardware version major of the CDC bootloader. */ + #define BOOTLOADER_HWVERSION_MAJOR 0x01 + + /** Hardware version minor of the CDC bootloader. */ + #define BOOTLOADER_HWVERSION_MINOR 0x00 + + /** Eight character bootloader firmware identifier reported to the host when requested */ + #define SOFTWARE_IDENTIFIER "CATERINA" + + #define CPU_PRESCALE(n) (CLKPR = 0x80, CLKPR = (n)) + #define LED_SETUP() DDRC |= (1<<7); DDRB |= (1<<0); DDRD |= (1<<5); + #define L_LED_OFF() PORTC &= ~(1<<7) + #define L_LED_ON() PORTC |= (1<<7) + #define L_LED_TOGGLE() PORTC ^= (1<<7) + + #define TX_LED_OFF() PORTD |= (1<<5) + #define TX_LED_ON() PORTD &= ~(1<<5) + #define TX_LED_TOGGLE() PORTD ^= (1<<5) + #define RX_LED_OFF() PORTB |= (1<<0) + #define RX_LED_ON() PORTB &= ~(1<<0) + #define RX_LED_TOGGLE() PORTB ^= (1<<0) + + /* Type Defines: */ + /** Type define for a non-returning pointer to the start of the loaded application in flash memory. */ + //typedef void (*AppPtr_t)(void) ATTR_NO_RETURN; + + /* Function Prototypes: */ + void StartSketch(void); + //void LEDPulse(void); + void ble_Task(uint8_t *pipes); + void SetupHardware(void); + +#endif + diff --git a/Source/ble-caterina/Descriptors.h b/Source/ble-caterina/Descriptors.h new file mode 100644 index 0000000..558a919 --- /dev/null +++ b/Source/ble-caterina/Descriptors.h @@ -0,0 +1,96 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2011. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * + * Header file for Descriptors.c. + */ + +#ifndef _DESCRIPTORS_H_ +#define _DESCRIPTORS_H_ + + /* Includes: */ + //#include + + /* Macros: */ + #if defined(__AVR_AT90USB1287__) + #define AVR_SIGNATURE_1 0x1E + #define AVR_SIGNATURE_2 0x97 + #define AVR_SIGNATURE_3 0x82 + #elif defined(__AVR_AT90USB647__) + #define AVR_SIGNATURE_1 0x1E + #define AVR_SIGNATURE_2 0x96 + #define AVR_SIGNATURE_3 0x82 + #elif defined(__AVR_AT90USB1286__) + #define AVR_SIGNATURE_1 0x1E + #define AVR_SIGNATURE_2 0x97 + #define AVR_SIGNATURE_3 0x82 + #elif defined(__AVR_AT90USB646__) + #define AVR_SIGNATURE_1 0x1E + #define AVR_SIGNATURE_2 0x96 + #define AVR_SIGNATURE_3 0x82 + #elif defined(__AVR_ATmega32U6__) + #define AVR_SIGNATURE_1 0x1E + #define AVR_SIGNATURE_2 0x95 + #define AVR_SIGNATURE_3 0x88 + #elif defined(__AVR_ATmega32U4__) + #define AVR_SIGNATURE_1 0x1E + #define AVR_SIGNATURE_2 0x95 + #define AVR_SIGNATURE_3 0x87 + #elif defined(__AVR_ATmega16U4__) + #define AVR_SIGNATURE_1 0x1E + #define AVR_SIGNATURE_2 0x94 + #define AVR_SIGNATURE_3 0x88 + #elif defined(__AVR_ATmega32U2__) + #define AVR_SIGNATURE_1 0x1E + #define AVR_SIGNATURE_2 0x95 + #define AVR_SIGNATURE_3 0x8A + #elif defined(__AVR_ATmega16U2__) + #define AVR_SIGNATURE_1 0x1E + #define AVR_SIGNATURE_2 0x94 + #define AVR_SIGNATURE_3 0x89 + #elif defined(__AVR_AT90USB162__) + #define AVR_SIGNATURE_1 0x1E + #define AVR_SIGNATURE_2 0x94 + #define AVR_SIGNATURE_3 0x82 + #elif defined(__AVR_ATmega8U2__) + #define AVR_SIGNATURE_1 0x1E + #define AVR_SIGNATURE_2 0x93 + #define AVR_SIGNATURE_3 0x89 + #elif defined(__AVR_AT90USB82__) + #define AVR_SIGNATURE_1 0x1E + #define AVR_SIGNATURE_2 0x94 + #define AVR_SIGNATURE_3 0x82 + #else + #error The selected AVR part is not currently supported by this bootloader. + #endif + +#endif + diff --git a/Source/ble-caterina/Makefile b/Source/ble-caterina/Makefile new file mode 100644 index 0000000..6277625 --- /dev/null +++ b/Source/ble-caterina/Makefile @@ -0,0 +1,744 @@ +# Hey Emacs, this is a -*- makefile -*- +#---------------------------------------------------------------------------- +# WinAVR Makefile Template written by Eric B. Weddington, Jöòg Wunsch, et al. +# >> Modified for use with the LUFA project. << +# +# Released to the Public Domain +# +# Additional material for this makefile was written by: +# Peter Fleury +# Tim Henigan +# Colin O'Flynn +# Reiner Patommel +# Markus Pfaff +# Sander Pool +# Frederik Rouleau +# Carlos Lamas +# Dean Camera +# Opendous Inc. +# Denver Gingerich +# +#---------------------------------------------------------------------------- +# On command line: +# +# make all = Make software. +# +# make clean = Clean out built project files. +# +# make coff = Convert ELF to AVR COFF. +# +# make extcoff = Convert ELF to AVR Extended COFF. +# +# make program = Download the hex file to the device, using avrdude. +# Please customize the avrdude settings below first! +# +# make doxygen = Generate DoxyGen documentation for the project (must have +# DoxyGen installed) +# +# make debug = Start either simulavr or avarice as specified for debugging, +# with avr-gdb or avr-insight as the front end for debugging. +# +# make filename.s = Just compile filename.c into the assembler code only. +# +# make filename.i = Create a preprocessed source file for use in submitting +# bug reports to the GCC project. +# +# To rebuild project do "make clean" then "make all". +#---------------------------------------------------------------------------- + +# USB vendor ID (VID) +# reuse of this VID by others is forbidden by USB-IF +# official Arduino LLC VID +# VID = 0x2341 +VID = 0x03EB + + +# USB product ID (PID) +# official Leonardo PID +# PID = 0x0036 +# RedBearLab Blend-Micro PID +PID = 0x2404 +# official Micro PID +# PID = 0x0037 +# official Esplora PID +# PID = 0x003C + +# MCU name +MCU = atmega32u4 + + +# Target architecture (see library "Board Types" documentation). +ARCH = AVR8 + + +# Target board (see library "Board Types" documentation, NONE for projects not requiring +# LUFA board drivers). If USER is selected, put custom board drivers in a directory called +# "Board" inside the application directory. +BOARD = USER + + +# Processor frequency. +# This will define a symbol, F_CPU, in all source code files equal to the +# processor frequency in Hz. You can then use this symbol in your source code to +# calculate timings. Do NOT tack on a 'UL' at the end, this will be done +# automatically to create a 32-bit value in your source code. +# +# This will be an integer division of F_USB below, as it is sourced by +# F_USB after it has run through any CPU prescalers. Note that this value +# does not *change* the processor frequency - it should merely be updated to +# reflect the processor speed set externally so that the code can use accurate +# software delays. +F_CPU = 16000000 + + +# Input clock frequency. +# This will define a symbol, F_USB, in all source code files equal to the +# input clock frequency (before any prescaling is performed) in Hz. This value may +# differ from F_CPU if prescaling is used on the latter, and is required as the +# raw input clock is fed directly to the PLL sections of the AVR for high speed +# clock generation for the USB and other AVR subsections. Do NOT tack on a 'UL' +# at the end, this will be done automatically to create a 32-bit value in your +# source code. +# +# If no clock division is performed on the input clock inside the AVR (via the +# CPU clock adjust registers or the clock division fuses), this will be equal to F_CPU. +F_USB = $(F_CPU) + + +# Starting byte address of the bootloader, as a byte address - computed via the formula +# BOOT_START = ((FLASH_SIZE_KB - BOOT_SECTION_SIZE_KB) * 1024) +# +# Note that the bootloader size and start address given in AVRStudio is in words and not +# bytes, and so will need to be doubled to obtain the byte address needed by AVR-GCC. +FLASH_SIZE_KB = 32 +BOOT_SECTION_SIZE_KB = 4 +BOOT_START = 0x$(shell echo "obase=16; ($(FLASH_SIZE_KB) - $(BOOT_SECTION_SIZE_KB)) * 1024" | bc) + + +# Output format. (can be srec, ihex, binary) +FORMAT = ihex + + +# Target file name (without extension). +TARGET = Caterina +# TARGET = Blend-Micro + + +# Object files directory +# To put object files in current directory, use a dot (.), do NOT make +# this an empty or blank macro! +OBJDIR = . + + +# Path to the LUFA library +LUFA_PATH = ../../../../../../LUFA/LUFA-111009 + + +# LUFA library compile-time options and predefined tokens +LUFA_OPTS = -D USB_DEVICE_ONLY +LUFA_OPTS += -D DEVICE_STATE_AS_GPIOR=0 +LUFA_OPTS += -D ORDERED_EP_CONFIG +LUFA_OPTS += -D FIXED_CONTROL_ENDPOINT_SIZE=8 +LUFA_OPTS += -D FIXED_NUM_CONFIGURATIONS=1 +LUFA_OPTS += -D USE_RAM_DESCRIPTORS +LUFA_OPTS += -D USE_STATIC_OPTIONS="(USB_DEVICE_OPT_FULLSPEED | USB_OPT_REG_ENABLED | USB_OPT_AUTO_PLL)" +LUFA_OPTS += -D NO_INTERNAL_SERIAL +LUFA_OPTS += -D NO_DEVICE_SELF_POWER +LUFA_OPTS += -D NO_DEVICE_REMOTE_WAKEUP +LUFA_OPTS += -D NO_SOF_EVENTS + +#LUFA_OPTS += -D NO_BLOCK_SUPPORT +#LUFA_OPTS += -D NO_EEPROM_BYTE_SUPPORT +#LUFA_OPTS += -D NO_FLASH_BYTE_SUPPORT +LUFA_OPTS += -D NO_LOCK_BYTE_WRITE_SUPPORT + + +# Create the LUFA source path variables by including the LUFA root makefile +include $(LUFA_PATH)/LUFA/makefile + + +# List C source files here. (C dependencies are automatically generated.) +SRC = $(TARGET).c \ + BLE/aci_setup.c \ + BLE/hal_aci_tl.c \ + BLE/lib_aci.c \ + BLE/dfu.c \ +# $(LUFA_SRC_USB) \ +# aci_setup.c \ +# ble_app.c \ +# acilib.c \ +# Descriptors.c \ + + + +# List C++ source files here. (C dependencies are automatically generated.) +CPPSRC = + + +# List Assembler source files here. +# Make them always end in a capital .S. Files ending in a lowercase .s +# will not be considered source files but generated files (assembler +# output from the compiler), and will be deleted upon "make clean"! +# Even though the DOS/Win* filesystem matches both .s and .S the same, +# it will preserve the spelling of the filenames, and gcc itself does +# care about how the name is spelled on its command-line. +ASRC = + + +# Optimization level, can be [0, 1, 2, 3, s]. +# 0 = turn off optimization. s = optimize for size. +# (Note: 3 is not always the best optimization level. See avr-libc FAQ.) +OPT = s + + +# Debugging format. +# Native formats for AVR-GCC's -g are dwarf-2 [default] or stabs. +# AVR Studio 4.10 requires dwarf-2. +# AVR [Extended] COFF format requires stabs, plus an avr-objcopy run. +DEBUG = dwarf-2 + + +# List any extra directories to look for include files here. +# Each directory must be seperated by a space. +# Use forward slashes for directory separators. +# For a directory that has spaces, enclose it in quotes. +EXTRAINCDIRS = $(LUFA_PATH)/ + + +# Compiler flag to set the C Standard level. +# c89 = "ANSI" C +# gnu89 = c89 plus GCC extensions +# c99 = ISO C99 standard (not yet fully implemented) +# gnu99 = c99 plus GCC extensions +CSTANDARD = -std=c99 + + +# Place -D or -U options here for C sources +CDEFS = -DF_CPU=$(F_CPU)UL +CDEFS += -DF_USB=$(F_USB)UL +CDEFS += -DBOARD=BOARD_$(BOARD) -DARCH=ARCH_$(ARCH) +CDEFS += -DBOOT_START_ADDR=$(BOOT_START)UL +CDEFS += -DDEVICE_VID=$(VID)UL +CDEFS += -DDEVICE_PID=$(PID)UL +CDEFS += $(LUFA_OPTS) + + +# Place -D or -U options here for ASM sources +ADEFS = -DF_CPU=$(F_CPU) +ADEFS += -DF_USB=$(F_USB)UL +ADEFS += -DBOARD=BOARD_$(BOARD) +ADEFS += -DBOOT_START_ADDR=$(BOOT_START)UL +ADEFS += $(LUFA_OPTS) + + +# Place -D or -U options here for C++ sources +CPPDEFS = -DF_CPU=$(F_CPU)UL +CPPDEFS += -DF_USB=$(F_USB)UL +CPPDEFS += -DBOARD=BOARD_$(BOARD) +CPPDEFS += -DBOOT_START_ADDR=$(BOOT_START)UL +CPPDEFS += $(LUFA_OPTS) +#CPPDEFS += -D__STDC_LIMIT_MACROS +#CPPDEFS += -D__STDC_CONSTANT_MACROS + + + +#---------------- Compiler Options C ---------------- +# -g*: generate debugging information +# -O*: optimization level +# -f...: tuning, see GCC manual and avr-libc documentation +# -Wall...: warning level +# -Wa,...: tell GCC to pass this to the assembler. +# -adhlns...: create assembler listing +CFLAGS = -g$(DEBUG) +CFLAGS += $(CDEFS) +CFLAGS += -O$(OPT) +CFLAGS += -funsigned-char +CFLAGS += -funsigned-bitfields +CFLAGS += -ffunction-sections +CFLAGS += -fno-inline-small-functions +CFLAGS += -fpack-struct +CFLAGS += -fshort-enums +CFLAGS += -fno-strict-aliasing +CFLAGS += -Wall +CFLAGS += -Wstrict-prototypes +#CFLAGS += -mshort-calls +#CFLAGS += -fno-unit-at-a-time +#CFLAGS += -Wundef +#CFLAGS += -Wunreachable-code +#CFLAGS += -Wsign-compare +CFLAGS += -Wa,-adhlns=$(<:%.c=$(OBJDIR)/%.lst) +CFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS)) +CFLAGS += $(CSTANDARD) + + +#---------------- Compiler Options C++ ---------------- +# -g*: generate debugging information +# -O*: optimization level +# -f...: tuning, see GCC manual and avr-libc documentation +# -Wall...: warning level +# -Wa,...: tell GCC to pass this to the assembler. +# -adhlns...: create assembler listing +CPPFLAGS = -g$(DEBUG) +CPPFLAGS += $(CPPDEFS) +CPPFLAGS += -O$(OPT) +CPPFLAGS += -funsigned-char +CPPFLAGS += -funsigned-bitfields +CPPFLAGS += -fpack-struct +CPPFLAGS += -fshort-enums +CPPFLAGS += -fno-exceptions +CPPFLAGS += -Wall +CPPFLAGS += -Wundef +#CPPFLAGS += -mshort-calls +#CPPFLAGS += -fno-unit-at-a-time +#CPPFLAGS += -Wstrict-prototypes +#CPPFLAGS += -Wunreachable-code +#CPPFLAGS += -Wsign-compare +CPPFLAGS += -Wa,-adhlns=$(<:%.cpp=$(OBJDIR)/%.lst) +CPPFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS)) +#CPPFLAGS += $(CSTANDARD) + + +#---------------- Assembler Options ---------------- +# -Wa,...: tell GCC to pass this to the assembler. +# -adhlns: create listing +# -gstabs: have the assembler create line number information; note that +# for use in COFF files, additional information about filenames +# and function names needs to be present in the assembler source +# files -- see avr-libc docs [FIXME: not yet described there] +# -listing-cont-lines: Sets the maximum number of continuation lines of hex +# dump that will be displayed for a given single line of source input. +ASFLAGS = $(ADEFS) -Wa,-adhlns=$(<:%.S=$(OBJDIR)/%.lst),-gstabs,--listing-cont-lines=100 + + +#---------------- Library Options ---------------- +# Minimalistic printf version +PRINTF_LIB_MIN = -Wl,-u,vfprintf -lprintf_min + +# Floating point printf version (requires MATH_LIB = -lm below) +PRINTF_LIB_FLOAT = -Wl,-u,vfprintf -lprintf_flt + +# If this is left blank, then it will use the Standard printf version. +PRINTF_LIB = +#PRINTF_LIB = $(PRINTF_LIB_MIN) +#PRINTF_LIB = $(PRINTF_LIB_FLOAT) + + +# Minimalistic scanf version +SCANF_LIB_MIN = -Wl,-u,vfscanf -lscanf_min + +# Floating point + %[ scanf version (requires MATH_LIB = -lm below) +SCANF_LIB_FLOAT = -Wl,-u,vfscanf -lscanf_flt + +# If this is left blank, then it will use the Standard scanf version. +SCANF_LIB = +#SCANF_LIB = $(SCANF_LIB_MIN) +#SCANF_LIB = $(SCANF_LIB_FLOAT) + + +MATH_LIB = -lm + + +# List any extra directories to look for libraries here. +# Each directory must be seperated by a space. +# Use forward slashes for directory separators. +# For a directory that has spaces, enclose it in quotes. +EXTRALIBDIRS = + + + +#---------------- External Memory Options ---------------- + +# 64 KB of external RAM, starting after internal RAM (ATmega128!), +# used for variables (.data/.bss) and heap (malloc()). +#EXTMEMOPTS = -Wl,-Tdata=0x801100,--defsym=__heap_end=0x80ffff + +# 64 KB of external RAM, starting after internal RAM (ATmega128!), +# only used for heap (malloc()). +#EXTMEMOPTS = -Wl,--section-start,.data=0x801100,--defsym=__heap_end=0x80ffff + +EXTMEMOPTS = + + + +#---------------- Linker Options ---------------- +# -Wl,...: tell GCC to pass this to linker. +# -Map: create map file +# --cref: add cross reference to map file +LDFLAGS = -Wl,-Map=$(TARGET).map,--cref +LDFLAGS += -Wl,--section-start=.text=$(BOOT_START) +LDFLAGS += -Wl,--relax +LDFLAGS += -Wl,--gc-sections +LDFLAGS += $(EXTMEMOPTS) +LDFLAGS += $(patsubst %,-L%,$(EXTRALIBDIRS)) +LDFLAGS += $(PRINTF_LIB) $(SCANF_LIB) $(MATH_LIB) +#LDFLAGS += -T linker_script.x + + + +#---------------- Programming Options (avrdude) ---------------- + +# Programming hardware +# Type: avrdude -c ? +# to get a full listing. +# +AVRDUDE_PROGRAMMER = avrispmkII + +# com1 = serial port. Use lpt1 to connect to parallel port. +AVRDUDE_PORT = usb + +AVRDUDE_WRITE_FLASH = -U flash:w:$(TARGET).hex +#AVRDUDE_WRITE_EEPROM = -U eeprom:w:$(TARGET).eep + + +# Uncomment the following if you want avrdude's erase cycle counter. +# Note that this counter needs to be initialized first using -Yn, +# see avrdude manual. +#AVRDUDE_ERASE_COUNTER = -y + +# Uncomment the following if you do /not/ wish a verification to be +# performed after programming the device. +#AVRDUDE_NO_VERIFY = -V + +# Increase verbosity level. Please use this when submitting bug +# reports about avrdude. See +# to submit bug reports. +#AVRDUDE_VERBOSE = -v -v + +AVRDUDE_FLAGS = -p $(MCU) -P $(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER) +AVRDUDE_FLAGS += $(AVRDUDE_NO_VERIFY) +AVRDUDE_FLAGS += $(AVRDUDE_VERBOSE) +AVRDUDE_FLAGS += $(AVRDUDE_ERASE_COUNTER) + + + +#---------------- Debugging Options ---------------- + +# For simulavr only - target MCU frequency. +DEBUG_MFREQ = $(F_CPU) + +# Set the DEBUG_UI to either gdb or insight. +# DEBUG_UI = gdb +DEBUG_UI = insight + +# Set the debugging back-end to either avarice, simulavr. +DEBUG_BACKEND = avarice +#DEBUG_BACKEND = simulavr + +# GDB Init Filename. +GDBINIT_FILE = __avr_gdbinit + +# When using avarice settings for the JTAG +JTAG_DEV = /dev/com1 + +# Debugging port used to communicate between GDB / avarice / simulavr. +DEBUG_PORT = 4242 + +# Debugging host used to communicate between GDB / avarice / simulavr, normally +# just set to localhost unless doing some sort of crazy debugging when +# avarice is running on a different computer. +DEBUG_HOST = localhost + + + +#============================================================================ + + +# Define programs and commands. +SHELL = sh +CC = avr-gcc +OBJCOPY = avr-objcopy +OBJDUMP = avr-objdump +SIZE = avr-size +AR = avr-ar rcs +NM = avr-nm +AVRDUDE = /Applications/avrdude -C /Applications/avrdude.conf -B 1 +REMOVE = rm -f +REMOVEDIR = rm -rf +COPY = cp +WINSHELL = cmd + + +# Define Messages +# English +MSG_ERRORS_NONE = Errors: none +MSG_BEGIN = -------- begin -------- +MSG_END = -------- end -------- +MSG_SIZE_BEFORE = Size before: +MSG_SIZE_AFTER = Size after: +MSG_COFF = Converting to AVR COFF: +MSG_EXTENDED_COFF = Converting to AVR Extended COFF: +MSG_FLASH = Creating load file for Flash: +MSG_EEPROM = Creating load file for EEPROM: +MSG_EXTENDED_LISTING = Creating Extended Listing: +MSG_SYMBOL_TABLE = Creating Symbol Table: +MSG_LINKING = Linking: +MSG_COMPILING = Compiling C: +MSG_COMPILING_CPP = Compiling C++: +MSG_ASSEMBLING = Assembling: +MSG_CLEANING = Cleaning project: +MSG_CREATING_LIBRARY = Creating library: + + + + +# Define all object files. +OBJ = $(SRC:%.c=$(OBJDIR)/%.o) $(CPPSRC:%.cpp=$(OBJDIR)/%.o) $(ASRC:%.S=$(OBJDIR)/%.o) + +# Define all listing files. +LST = $(SRC:%.c=$(OBJDIR)/%.lst) $(CPPSRC:%.cpp=$(OBJDIR)/%.lst) $(ASRC:%.S=$(OBJDIR)/%.lst) + + +# Compiler flags to generate dependency files. +GENDEPFLAGS = -MMD -MP -MF .dep/$(@F).d + + +# Combine all necessary flags and optional flags. +# Add target processor to flags. +ALL_CFLAGS = -mmcu=$(MCU) -I. $(CFLAGS) $(GENDEPFLAGS) +ALL_CPPFLAGS = -mmcu=$(MCU) -I. -x c++ $(CPPFLAGS) $(GENDEPFLAGS) +ALL_ASFLAGS = -mmcu=$(MCU) -I. -x assembler-with-cpp $(ASFLAGS) + + + + + +# Default target. +all: begin gccversion sizebefore build sizeafter end + +# Change the build target to build a HEX file or a library. +build: elf hex eep lss sym +#build: lib + + +elf: $(TARGET).elf +hex: $(TARGET).hex +eep: $(TARGET).eep +lss: $(TARGET).lss +sym: $(TARGET).sym +LIBNAME=lib$(TARGET).a +lib: $(LIBNAME) + + + +# Eye candy. +# AVR Studio 3.x does not check make's exit code but relies on +# the following magic strings to be generated by the compile job. +begin: + @echo + @echo $(MSG_BEGIN) + +end: + @echo $(MSG_END) + @echo + + +# Display size of file. +HEXSIZE = $(SIZE) --target=$(FORMAT) $(TARGET).hex +ELFSIZE = $(SIZE) $(MCU_FLAG) $(FORMAT_FLAG) $(TARGET).elf +MCU_FLAG = $(shell $(SIZE) --help | grep -- --mcu > /dev/null && echo --mcu=$(MCU) ) +FORMAT_FLAG = $(shell $(SIZE) --help | grep -- --format=.*avr > /dev/null && echo --format=avr ) + + +sizebefore: + @if test -f $(TARGET).elf; then echo; echo $(MSG_SIZE_BEFORE); $(ELFSIZE); \ + 2>/dev/null; echo; fi + +sizeafter: + @if test -f $(TARGET).elf; then echo; echo $(MSG_SIZE_AFTER); $(ELFSIZE); \ + 2>/dev/null; echo; fi + + + +# Display compiler version information. +gccversion : + @$(CC) --version + + +# Program the device. +program: $(TARGET).hex $(TARGET).eep + $(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH) $(AVRDUDE_WRITE_EEPROM) + + +# Generate avr-gdb config/init file which does the following: +# define the reset signal, load the target file, connect to target, and set +# a breakpoint at main(). +gdb-config: + @$(REMOVE) $(GDBINIT_FILE) + @echo define reset >> $(GDBINIT_FILE) + @echo SIGNAL SIGHUP >> $(GDBINIT_FILE) + @echo end >> $(GDBINIT_FILE) + @echo file $(TARGET).elf >> $(GDBINIT_FILE) + @echo target remote $(DEBUG_HOST):$(DEBUG_PORT) >> $(GDBINIT_FILE) +ifeq ($(DEBUG_BACKEND),simulavr) + @echo load >> $(GDBINIT_FILE) +endif + @echo break main >> $(GDBINIT_FILE) + +debug: gdb-config $(TARGET).elf +ifeq ($(DEBUG_BACKEND), avarice) + @echo Starting AVaRICE - Press enter when "waiting to connect" message displays. + @$(WINSHELL) /c start avarice --jtag $(JTAG_DEV) --erase --program --file \ + $(TARGET).elf $(DEBUG_HOST):$(DEBUG_PORT) + @$(WINSHELL) /c pause + +else + @$(WINSHELL) /c start simulavr --gdbserver --device $(MCU) --clock-freq \ + $(DEBUG_MFREQ) --port $(DEBUG_PORT) +endif + @$(WINSHELL) /c start avr-$(DEBUG_UI) --command=$(GDBINIT_FILE) + + + + +# Convert ELF to COFF for use in debugging / simulating in AVR Studio or VMLAB. +COFFCONVERT = $(OBJCOPY) --debugging +COFFCONVERT += --change-section-address .data-0x800000 +COFFCONVERT += --change-section-address .bss-0x800000 +COFFCONVERT += --change-section-address .noinit-0x800000 +COFFCONVERT += --change-section-address .eeprom-0x810000 + + + +coff: $(TARGET).elf + @echo + @echo $(MSG_COFF) $(TARGET).cof + $(COFFCONVERT) -O coff-avr $< $(TARGET).cof + + +extcoff: $(TARGET).elf + @echo + @echo $(MSG_EXTENDED_COFF) $(TARGET).cof + $(COFFCONVERT) -O coff-ext-avr $< $(TARGET).cof + + + +# Create final output files (.hex, .eep) from ELF output file. +%.hex: %.elf + @echo + @echo $(MSG_FLASH) $@ + $(OBJCOPY) -O $(FORMAT) -R .eeprom -R .fuse -R .lock $< $@ + +%.eep: %.elf + @echo + @echo $(MSG_EEPROM) $@ + -$(OBJCOPY) -j .eeprom --set-section-flags=.eeprom="alloc,load" \ + --change-section-lma .eeprom=0 --no-change-warnings -O $(FORMAT) $< $@ || exit 0 + +# Create extended listing file from ELF output file. +%.lss: %.elf + @echo + @echo $(MSG_EXTENDED_LISTING) $@ + $(OBJDUMP) -h -S -z $< > $@ + +# Create a symbol table from ELF output file. +%.sym: %.elf + @echo + @echo $(MSG_SYMBOL_TABLE) $@ + $(NM) -n $< > $@ + + + +# Create library from object files. +.SECONDARY : $(TARGET).a +.PRECIOUS : $(OBJ) +%.a: $(OBJ) + @echo + @echo $(MSG_CREATING_LIBRARY) $@ + $(AR) $@ $(OBJ) + + +# Link: create ELF output file from object files. +.SECONDARY : $(TARGET).elf +.PRECIOUS : $(OBJ) +%.elf: $(OBJ) + @echo + @echo $(MSG_LINKING) $@ + $(CC) $(ALL_CFLAGS) $^ --output $@ $(LDFLAGS) + + +# Compile: create object files from C source files. +$(OBJDIR)/%.o : %.c + @echo + @echo $(MSG_COMPILING) $< + $(CC) -c $(ALL_CFLAGS) $< -o $@ + + +# Compile: create object files from C++ source files. +$(OBJDIR)/%.o : %.cpp + @echo + @echo $(MSG_COMPILING_CPP) $< + $(CC) -c $(ALL_CPPFLAGS) $< -o $@ + + +# Compile: create assembler files from C source files. +%.s : %.c + $(CC) -S $(ALL_CFLAGS) $< -o $@ + + +# Compile: create assembler files from C++ source files. +%.s : %.cpp + $(CC) -S $(ALL_CPPFLAGS) $< -o $@ + + +# Assemble: create object files from assembler source files. +$(OBJDIR)/%.o : %.S + @echo + @echo $(MSG_ASSEMBLING) $< + $(CC) -c $(ALL_ASFLAGS) $< -o $@ + + +# Create preprocessed source for use in sending a bug report. +%.i : %.c + $(CC) -E -mmcu=$(MCU) -I. $(CFLAGS) $< -o $@ + + +# Target: clean project. +clean: begin clean_list end + +clean_list : + @echo + @echo $(MSG_CLEANING) + $(REMOVE) $(TARGET).hex + $(REMOVE) $(TARGET).eep + $(REMOVE) $(TARGET).cof + $(REMOVE) $(TARGET).elf + $(REMOVE) $(TARGET).map + $(REMOVE) $(TARGET).sym + $(REMOVE) $(TARGET).lss + $(REMOVE) $(SRC:%.c=$(OBJDIR)/%.o) $(CPPSRC:%.cpp=$(OBJDIR)/%.o) $(ASRC:%.S=$(OBJDIR)/%.o) + $(REMOVE) $(SRC:%.c=$(OBJDIR)/%.lst) $(CPPSRC:%.cpp=$(OBJDIR)/%.lst) $(ASRC:%.S=$(OBJDIR)/%.lst) + $(REMOVE) $(SRC:.c=.s) + $(REMOVE) $(SRC:.c=.d) + $(REMOVE) $(SRC:.c=.i) + $(REMOVEDIR) .dep + +doxygen: + @echo Generating Project Documentation \($(TARGET)\)... + @doxygen Doxygen.conf + @echo Documentation Generation Complete. + +clean_doxygen: + rm -rf Documentation + +checksource: + @for f in $(SRC) $(CPPSRC) $(ASRC); do \ + if [ -f $$f ]; then \ + echo "Found Source File: $$f" ; \ + else \ + echo "Source File Not Found: $$f" ; \ + fi; done + + +# Create object files directory +$(shell mkdir $(OBJDIR) 2>/dev/null) + + +# Include the dependency files. +-include $(shell mkdir .dep 2>/dev/null) $(wildcard .dep/*) + + +# Listing of phony targets. +.PHONY : all begin finish end sizebefore sizeafter gccversion \ +build elf hex eep lss sym coff extcoff doxygen clean \ +clean_list clean_doxygen program debug gdb-config checksource +