Subversion Repositories MK3Mag

Compare Revisions

Ignore whitespace Rev 50 → Rev 51

/tags/V0.21b/Compass.pnproj
0,0 → 1,0
<Project name="avr_ctrl"><File path="uart.h"></File><File path="main.c"></File><File path="main.h"></File><File path="makefile"></File><File path="uart.c"></File><File path="timer0.c"></File><File path="timer0.h"></File><File path="analog.h"></File><File path="analog.c"></File><File path="twislave.c"></File><File path="twislave.h"></File></Project>
/tags/V0.21b/Compassl.pnps
0,0 → 1,0
<pd><ViewState><e p="avr_ctrl" x="true"></e></ViewState></pd>
/tags/V0.21b/Hex-Files/BootLoader_MEGA168_8MHZ_V0.2.hex
0,0 → 1,61
:1038000011241FBECFEFD4E0DEBFCDBF11E0A0E09A
:10381000B1E0EEEAFBE302C005900D92A030B107E3
:10382000D9F711E0A0E0B1E001C01D92A238B107C4
:10383000E1F70C943B1C0C941D1C0895982F80916B
:10384000C00085FFFCCF9093C60008958091C00012
:103850008823E4F78091C600992708958DE40E949B
:103860001E1C8BE40E941E1C82E40E941E1C8CE421
:103870000E941E1C0895CFEFD4E0DEBFCDBFE0E074
:10388000F0E004917F01992494BE98E10FB6F8947A
:1038900090936000109260000FBE9092C50080E18E
:1038A0008093C4008091C00082608093C000909398
:1038B000C10086E08093C200EF01192D8091C00005
:1038C00087FF0DC0113031F48091C6008A3A89F12A
:1038D00010E005C08091C6008B3109F411E0CE01E3
:1038E00021968436910500F10F3F41F0002331F01D
:1038F000E0910001F0910101099516C08AE00E9453
:103900001E1C8DE00E941E1C86E50E941E1C80E38A
:103910000E941E1C8EE20E941E1C82E30E941E1C3E
:103920008AE30E941E1C05C080E29EE40197F1F725
:10393000C5CF0E942E1C0E94261C813611F489E5F9
:1039400033C1813471F40E94261CE82EFF24FE2C22
:10395000EE240E94261C9927E82AF92AF694E79477
:10396000F1C0823641F489E50E941E1C80E00E946D
:103970001E1C80E819C1823409F075C00E94261C03
:103980000E94261CD82E0E94261C082FB2E0AB2EC7
:10399000B1E0BB2E10E0E5010894A11CB11C1D157F
:1039A00018F40E94261C01C08FEF88831F5F17FF49
:1039B000F2CF38E7931609F0D4C0063409F03DC0C1
:1039C0008FEFE81687E3F80608F033C0CD2DA70186
:1039D00066277727440F551F661F771F6A017B01F3
:1039E000A2E0B1E011E08D9199272D913327322F7C
:1039F0002227822B932B0C01FA0110935700E89594
:103A000011244E5F5F4F6F4F7F4FC25061F785E0CB
:103A1000F60180935700E89507B600FCFDCF81E1E1
:103A200080935700E89576956795579547957A0165
:103A300089C080E00E941E1C85C0053409F082C048
:103A4000F7012D2DA2E0B1E0E1BD8F2F992782BDB6
:103A50008D9180BD3196FA9AF99AF999FECF21504D
:103A600099F77F016FC0873609F03DC00E94261C80
:103A70000E94261CC82F0E94261C863419F5C701F7
:103A8000AA27BB276C017D01CC0CDD1CEE1CFF1CA2
:103A9000F60105911491802F0E941E1C812F9927F9
:103AA0000E941E1C82E090E0A0E0B0E0C80ED91E8B
:103AB000EA1EFB1EC25061F7F694E794D794C794B0
:103AC000760139CF853409F036CFE1BC8F2D9927A7
:103AD00082BDF89A0894E11CF11C80B50E941E1C5E
:103AE000C15099F728CF853601F598E7991651F519
:103AF00080E090E0A0E0B0E023E0FC0120935700DC
:103B0000E89507B600FCFDCF80589F4FAF4FBF4FE1
:103B10008F3F37E3930730E0A30730E0B30768F344
:103B200081E180935700E8950DC0853469F488E100
:103B300090E02CE00FB6F894A895809360000FBE3B
:103B4000209360008DE030C08035E1F38C34D1F3F8
:103B5000803711F483E528C0843729F488E70E9470
:103B60001E1C80E021C0843521F40E94261C982E62
:103B7000E9CF8B3109F4DDCE8A3A09F4DACE863505
:103B800029F480E30E941E1C82E30EC0833741F4B7
:103B900086E00E941E1C84E90E941E1C8EE104C067
:0E3BA0008B3109F4C8CE8FE30E941E1CC4CEE8
:0400000300003800C1
:00000001FF
/tags/V0.21b/Hex-Files/MK3Mag_MEGA168_V0_21b_SVN48.hex
0,0 → 1,604
:100000000C946B000C9486000C9486000C94860073
:100010000C9486000C9486000C9486000C94860048
:100020000C9486000C9486000C9486000C94860038
:100030000C9486000C9486000C9486000C94860028
:100040000C94090C0C9486000C9431080C948600D6
:100050000C94FB070C9486000C9486000C9486008C
:100060000C94120D0C94860007BAA57A2C3BDA90FA
:10007000C5BC8BFC663CFD10F8BD4D83923DB63A85
:100080009EBE5BBFCA3FC90FDA000829573F9F2DAC
:1000900049CBA5310F76C73493F27E37D00D013AA4
:1000A000B60B613D2AAAAB3F0000003F8000000074
:1000B000083B3BD74ABC846E023D2FC1FEBD9A313E
:1000C000743DDA3D83BE117FC73E4CBBE5BEAAAA94
:1000D0006C3F8000000011241FBECFEFD4E0DEBFD4
:1000E000CDBF13E0A0E0B1E0E2E8F3E202C005908A
:1000F0000D92A431B107D9F714E0A4E1B3E001C037
:100100001D92A738B107E1F70C946A060C94000021
:10011000CF93DF9340917D0350917E0380915E03E6
:1001200090915F03481B590B5093860340938503BE
:10013000809162039091630320915C0330915D0391
:10014000821B930B909361038093600380918103E2
:10015000909182032091830330918403821B930B3F
:100160009093800380937F03209164033091650313
:1001700021153105F9F08091660390916703481BC2
:10018000590BCA01AA2797FDA095BA2F4AE0880FFC
:10019000991FAA1FBB1F4A95D1F7442737FD4095E9
:1001A000542FBC01CD010E94661130932903209386
:1001B000280304C030932903209328034091680347
:1001C000509169034115510509F44AC080916003BB
:1001D0009091610320916A0330916B03821B930B12
:1001E000AA2797FDA095BA2F3AE0880F991FAA1F5A
:1001F000BB1F3A95D1F7EA01EE27D7FDE095FE2F18
:100200009E01AF01BC01CD010E946611309327030E
:100210002093260380917F039091800320916E03A9
:1002200030916F03821B930BAA2797FDA095BA2FDD
:100230002AE0880F991FAA1FBB1F2A95D1F720918A
:100240006C0330916D03442737FD4095542FBC015A
:10025000CD010E946611309325032093240308C02A
:100260005093270340932603509325034093240380
:1002700080915103882309F4B9C040912203509121
:1002800023038091720390917303481B590B509381
:100290001D0340931C038091200390912103209122
:1002A000760330917703821B930B90931B0380930B
:1002B0001A0380917A0390917B0320911E03309161
:1002C0001F03821B930B90931903809318034938E3
:1002D00051051CF080EE9CEF3CC0EFEF48375E0705
:1002E0001CF480E293E035C0CA01AA2797FDA095CF
:1002F000BA2FBC01CD010E94850FDC01CB0120E0AB
:1003000030E04AE053E4BC01CD010E94220FDC0141
:10031000CB01BC01CD010E94AF0EDC01CB0120E07E
:1003200030E041EE54ECBC01CD010E947110DC01C3
:10033000CB012BED3FE049E450E4BC01CD010E942C
:10034000220FDC01CB01BC01CD010E94680FDC0152
:10035000CB01909317038093160380911A03909119
:100360001B03893891051CF080E293E03BC0FFEF4E
:1003700088379F071CF480EE9CEF34C0AA2797FDB6
:10038000A095BA2FBC01CD010E94850FDC01CB01E5
:1003900020E030E04AE053E4BC01CD010E94220F8E
:1003A000DC01CB01BC01CD010E94AF0EDC01CB0111
:1003B00020E030E041EE54E4BC01CD010E94711018
:1003C000DC01CB012BED3FE049E450E4BC01CD0161
:1003D0000E94220FDC01CB01BC01CD010E94680FFD
:1003E000DC01CB019093150380931403DF91CF912F
:1003F00008952F923F924F925F926F927F928F92C9
:100400009F92AF92BF92CF92DF92EF92FF920F93A3
:100410001F93CF93DF93CDB7DEB724970FB6F89431
:10042000DEBF0FBECDBF0F2EF0E02F2EF0E03F2E2F
:10043000F0E04F2EF0E05F2EF02D82017101298255
:100440003A824B825C8280912A0390912B030E9416
:100450006C0C882391F080917C03813029F08BB162
:1004600090E889278BB901C05F9A86E990E00E94E5
:10047000630C90932B0380932A03809102019927A8
:10048000009719F00197A1F042C080912803909144
:100490002903AA2797FDA095BA2FBC01CD010E9480
:1004A000850F7B018C01809126039091270315C055
:1004B0008091260390912703AA2797FDA095BA2F34
:1004C000BC01CD010E94850F7B018C018091280326
:1004D00090912903909581959F4FAA2797FDA0950C
:1004E000BA2FBC01CD010E94850F1B012C01809108
:1004F000240390912503AA2797FDA095BA2FBC014C
:10050000CD010E94850F69837A838B839C838091C0
:100510000301992781309105A1F0823091051CF4E7
:10052000892B21F022C00297B9F01FC0F894809166
:100530006D0490916E0480906F0490907004789494
:1005400017C0F8948091BA039091BB038090BC03CC
:100550009090BD0378940CC080911603909117037E
:10056000809014039090150303C088249924C4013B
:10057000AA2797FDA095BA2FBC01CD010E94850F37
:10058000DC01CB012BED3FE049E450E4BC01CD019F
:100590000E947110DC01CB0120E030E041EE54E418
:1005A000BC01CD010E94220F5B016C01C401AA278E
:1005B00097FDA095BA2FBC01CD010E94850FDC01EB
:1005C000CB012BED3FE049E450E4BC01CD010E949A
:1005D0007110DC01CB0120E030E041EE54E4BC01BD
:1005E000CD010E94220F3B014C01C601B5010E94C2
:1005F0001C0FDC01CB019C01AD01C801B7010E94B9
:1006000071107B018C01C601B5010E94B910DC019B
:10061000CB019C01AD0169817A818B819C810E9413
:100620007110DC01CB019C01AD01C801B7010E9432
:100630006C0E5B016C01C401B3010E941C0FDC0154
:10064000CB019C01AD01C201B1010E9471107B017F
:100650008C01C401B3010E94B910DC01CB019C01E3
:10066000AD0169817A818B819C810E947110DC01CE
:10067000CB019C01AD01C801B7010E946D0E7B0149
:100680008C01C601B5010E94680FDC01CB0190937B
:10069000FB038093FA03C801B7010E94680FDC01D5
:1006A000CB019093FD038093FC03A6019501C80143
:1006B000B7010E94E90EDC01CB0120E030E044E309
:1006C00053E4BC01CD010E947110DC01CB012BED84
:1006D0003FE049E450E4BC01CD010E94220FDC015F
:1006E000CB01BC01CD010E94680FDC01CB019C0154
:1006F00097FF04C0309521953F4F05C088E691E0F3
:10070000821B930B9C0180917C03813011F02FEFB1
:100710003FEFF894C90188599E4F815D924028F4BB
:10072000309301012093000106C08FEF9FEF90935B
:10073000010180930001789424960FB6F894DEBFEF
:100740000FBECDBFDF91CF911F910F91FF90EF9022
:10075000DF90CF90BF90AF909F908F907F906F90E1
:100760005F904F903F902F900895CF9380916A04AF
:10077000882311F0C82F02C0C091C003C63010F00A
:10078000C0E038C0CC23B1F180912A0390912B03B3
:100790000E946C0C882321F480912C03C81789F1E6
:1007A0004091390380913A0340FF03C0882329F424
:1007B00002C0882311F05F9801C05F9A242F33276D
:1007C0002F5F3F4F8C2F9927880F991F28173907C4
:1007D0002CF0109239038CED95E005C04F5F4093EB
:1007E000390384E690E00E94630C90932B0380937E
:1007F0002A0307C080913A03882311F05F9A01C051
:100800005F988C2F99278330910509F409C18430B2
:1008100091053CF48130910561F0029709F43EC0E6
:1008200001C18430910509F46EC0059709F489C0AF
:10083000F9C020E137E230932E0320932D0380EF9F
:1008400098ED9093300380932F03309332032093DD
:100850003103909334038093330330933603209312
:10086000350390933803809337038091220390914E
:1008700023039093730380937203809120039091DC
:100880002103909377038093760380911E039091C8
:100890001F0390937B0380937A03C2C0209185034A
:1008A0003091860380912D0390912E0328173907EC
:1008B00024F430932E0320932D0380912F039091E5
:1008C00030038217930724F43093300320932F03CF
:1008D0002091600330916103809131039091320344
:1008E0002817390724F43093320320933103809181
:1008F00033039091340382179307FCF4309334034D
:10090000209333031AC020917F033091800380919C
:100910003503909136032817390724F430933603B2
:100920002093350380913703909138038217930702
:1009300024F4309338032093370381E080933A0303
:1009400071C080912C03C81709F46AC0E4E6F3E093
:1009500020912F033091300380912D0390912E032D
:10096000D901A81BB90BB0936503A0936403820F50
:10097000931F97FD019695958795909367038093B4
:1009800066032091330330913403809131039091B9
:100990003203B901681B790B709369036093680394
:1009A000820F931F97FD01969595879590936B0302
:1009B00080936A0320913703309138038091350387
:1009C00090913603A901481B590B50936D03409336
:1009D0006C03820F931F97FD0196959587959093D1
:1009E0006F0380936E03A739B105D4F067397105A1
:1009F000BCF047395105A4F081E080937C035F98F7
:100A0000A0E0B0E089E1182E0E94A81180ED97E0E7
:100A10000E94630C90932B0380932A031092390356
:100A200010923A03C0932C03CF910895809128032C
:100A3000909129039093C5038093C403809126036A
:100A4000909127039093C7038093C603809124035A
:100A5000909125039093C9038093C80380918503E7
:100A6000909186039093CB038093CA038091600397
:100A7000909161039093CD038093CC0380917F0389
:100A8000909180039093CF038093CE032091030134
:100A9000822F992781309105A9F0823091051CF4AD
:100AA000892BE9F02CC0029751F5809116039091A3
:100AB00017039093D1038093D003809114039091F6
:100AC000150319C08091BA039091BB039093D10391
:100AD0008093D0038091BC039091BD030CC08091A2
:100AE0006D0490916E049093D1038093D003809114
:100AF0006F04909170049093D3038093D2038091FC
:100B00006603909167039093D5038093D4038091FB
:100B10006403909165039093D7038093D6038091EB
:100B20006A0390916B039093D9038093D8038091CB
:100B30006803909169039093DB038093DA038091BB
:100B40006E0390916F039093DD038093DC0380919B
:100B50006C0390916D039093DF038093DE0380918B
:100B60006A04882311F48091C00399279093E103CC
:100B70008093E00380910001909101019093E30341
:100B80008093E2038091BE0399279093E5038093BD
:100B9000E4038091BF0399279093E7038093E603D2
:100BA00080911C0390911D039093E9038093E803C7
:100BB00080911A0390911B039093EB038093EA03B7
:100BC00080911803909119039093ED038093EC03A7
:100BD00080912203909123039093EF038093EE037F
:100BE00080912003909121039093F1038093F0036F
:100BF00080911E0390911F039093F3038093F2035F
:100C000080917203909173039093F5038093F403A2
:100C100080917603909177039093F7038093F60386
:100C200080917A0390917B039093F9038093F8036A
:100C3000822F99279093FF038093FE03089580915C
:100C400051038823D1F182E00E94840C2091220379
:100C500030912303280F391F37FF02C02F5F3F4F0A
:100C600035952795309323032093220383E00E9438
:100C7000840C2091200330912103280F391F37FF66
:100C800002C02F5F3F4F3595279530932103209366
:100C9000200386E00E94840C20911E0330911F03E4
:100CA000280F391F37FF02C02F5F3F4F359527951B
:100CB00030931F0320931E03089510922303109274
:100CC0002203109221031092200310921F0310920E
:100CD0001E030895CFEFD4E0DEBFCDBF3E98469A05
:100CE0000E94690E0E94F30B0E9435070E94990C26
:100CF0000E94D50C789480915103882321F084E0E0
:100D000091E00E94DA0B5F9A88EC90E00E94630CFD
:100D100090932B0380932A03E4E6F3E0A0E0B0E095
:100D200089E1182E0E94A3111092C00310926A0448
:100D30008BB18F798BB982E090E00E94770C80E0D4
:100D40000E94840C90937E0380937D0381E00E9437
:100D5000840C909581959F4F90938203809381039B
:100D600087E00E94840C90936303809362030E9447
:100D70001F0681E090E00E94770C8BB180668BB9F2
:100D800082E090E00E94770C80E00E94840C9093B7
:100D90005F0380935E0381E00E94840C90958195AF
:100DA0009F4F909384038093830387E00E94840C79
:100DB00090935D0380935C030E941F0681E090E0A6
:100DC0000E94770C0E9488008091C003882321F440
:100DD00080916A04882319F00E94B50302C00E9422
:100DE000F9010E942A0A80915203882319F0815048
:100DF0008093520380913B03882319F081508093A4
:100E00003B0380913B03882351F480915203882354
:100E100031F482E08093030181E0809302018091AC
:100E20003C03882351F00E94DD070E94C90A80918B
:100E30003C03815080933C037BCF0E94EA0778CF2C
:100E4000CF93C82F8091C10083FF0BC0CA3019F423
:100E50008DE00E9420078091C00085FFFCCFC093E9
:100E6000C60080E090E0CF9108951F93CF93CFB755
:100E700020E130E0F8948091C1008F778093C10029
:100E80008091C1008F7B8093C10050985898519AEF
:100E90005998832F99278093C5002093C40080918F
:100EA000C00082608093C0008091C2008F778093E1
:100EB000C2008091C2008F7B8093C2008091C200EB
:100EC0008F7D8093C2008091C2008F7E8093C2008C
:100ED0008091C200877F8093C2008091C1008B7F88
:100EE0008093C1008091C20084608093C200809191
:100EF000C20082608093C2008091C10080618093B3
:100F0000C1008091C10088608093C1008091C000C1
:100F100087FF03C08091C600F9CF8091C10080682F
:100F20008093C1008091C10080648093C100809152
:100F30001103909112030E94630C909369048093B3
:100F400068041092440310924203109241031092DD
:100F5000400391E0909313031092A50385E18093E1
:100F6000A6039093A9031AE01093A7031092A80375
:100F7000812F0E94200783E40E94200780E50E94C1
:100F800020078AE30E94200786E50E94200780E36D
:100F90000E9420078EE20E94200782E30E94200721
:100FA00081E30E94200782E60E942007812F0E9491
:100FB0002007CFBFCF911F910895519A59988091E2
:100FC000C10088608093C1008091C10080648093DB
:100FD000C1000895809113038823E1F38091C1003B
:100FE0008F7B8093C1008091C100877F8093C10077
:100FF0005198599808951F920F920FB60F9211248D
:101000008F939F93EF93FF93809113038823E1F4D1
:1010100080914503909146030196909346038093F7
:101020004503FC01EC5FFB4FE081ED3019F08436A5
:10103000910539F4109246031092450381E08093A4
:101040001303E093C60004C01092460310924503B8
:10105000FF91EF919F918F910F900FBE0F901F9076
:1010600018951F920F920FB60F9211242F933F9352
:101070004F935F938F939F93AF93BF93CF93DF93E0
:10108000EF93FF935091C60080914403882309F0A9
:101090006EC040914903442371F4533279F4509364
:1010A000870381E08093490383E290E090934803B3
:1010B000809347035CC04E3108F055C02091470330
:1010C00030914803E42FFF275D3069F0E957FC4F6A
:1010D00050834F5F40934903250F311D30934803E0
:1010E0002093470344C0DF01A957BC4FFD0132974D
:1010F0008081281B3109ED0121978881281B310946
:10110000C9019F709093480380934703689415F832
:10111000969587951694E1F7982F935C2F7330700E
:10112000235C80819817D1F488812817B9F45C93E7
:101130004F5F4093430381E0809344038091890390
:10114000823571F488E190E02CE00FB6F894A89510
:10115000809360000FBE2093600002C01092440391
:101160001092490304C08093490380934403FF9184
:10117000EF91DF91CF91BF91AF919F918F915F914F
:101180004F913F912F910F900FBE0F901F90189588
:10119000AC01A0E0B0E09D01A817B90748F4E4E075
:1011A000F4E08191280F311D1196A417B507C8F3FB
:1011B0003F70FD01EC5FFB4FC90176E09695879586
:1011C0007A95E1F7835C80831196FD01EC5FFB4F1C
:1011D0002F733070822F835C8083AB5FBB4F8DE0B9
:1011E0008C9310921303809104048093C600089599
:1011F000BF92CF92DF92EF92FF920F931F93CF9304
:10120000DF93CDB7DEB72C859D850E85BB2483E2A9
:10121000809304049F59909305042093060433E0BF
:10122000E32EF12C002309F49EC0CF84D888BE01A0
:101230006D5E7F4FA989BA890150109709F493C058
:101240001097B9F0F601EB0DF11DB3949081119751
:1012500091F4002349F1FB016E5F7F4FDB01C080F9
:10126000D1806E5F7F4F0D90BC91A02DBB240150AB
:1012700002C090E019C01097B9F0F601EB0DF11D16
:10128000B3944081119791F4002341F1FB016E5F0B
:101290007F4FDB01C080D1806E5F7F4F0D90BC918E
:1012A000A02DBB24015002C040E018C01097B1F03F
:1012B000F601EB0DF11DB3941081119781F4002319
:1012C00071F0FB013296DB01CD90DC90BF016E5FC7
:1012D0007F4FA081B181BB24015001C010E0F70114
:1012E000EC5FFB4F892F86958695835C80830894FD
:1012F000E11CF11CF701EC5FFB4F892F99278370EC
:10130000907024E0880F991F2A95E1F755279A01DC
:1013100094E0369527959A95E1F7822B835C80833C
:101320000894E11CF11CF701EC5FFB4F4F7050700B
:10133000440F551F440F551F812F992726E096957E
:1013400087952A95E1F7842B835C80830894E11CC0
:10135000F11CF701EC5FFB4F1F73135C10830894C3
:10136000E11CF11C6ACFC7010E94C808DF91CF9130
:101370001F910F91FF90EF90DF90CF90BF90089555
:10138000A3E07A2F409143034650442309F458C008
:10139000E72FFF27E957FC4F80818D537F5FE72FB1
:1013A000FF27E957FC4F20812D537F5FE72FFF2751
:1013B000E957FC4F30813D537F5FE72FFF27E95707
:1013C000FC4F60816D537F5F9927880F991F880FAD
:1013D000991F522F52955F70582B822F99278F702B
:1013E0009070F4E0880F991FFA95E1F7232F269566
:1013F0002695282B832F992783709070E6E0880F1D
:10140000991FEA95E1F7682B41504F3FC9F0EA2F49
:10141000FF27E957FC4F5083AF5F41504F3F81F0AA
:10142000EA2FFF27E957FC4F2083AF5F41504F3F22
:1014300039F0EA2FFF27E957FC4F6083AF5FA5CF54
:101440008AE893E09093420380934103A350A093D2
:101450004003089580914403882309F499C00E94B1
:10146000C00980918803843619F5809189039927F2
:101470008B36910519F087379105D1F4AAEBB3E0CB
:10148000E0914103F091420388E001900D92815078
:10149000E1F780913F03886080933F0381E0809370
:1014A00003018091C103809302018FEF80933B037E
:1014B00080918903992784369105C1F1853691057C
:1014C00044F48136910509F448C08236910589F0CB
:1014D00057C08836910509F450C0893691052CF41F
:1014E0008736910509F444C04BC08637910589F1D0
:1014F00047C0AFEAB3E0E0914103F09142039BE0C3
:1015000001900D929150E1F78091B10381FF09C0E4
:101510008091C0038F5F8093C003863011F4909355
:10152000C0038091B80380933D0327C0E09141033D
:10153000F091420390818AE0989FC001112490931A
:10154000120380931103892BC1F080913F038260C5
:1015500012C080913F0381600EC0E0914103F09181
:101560004203808180933E0380913F03846003C0E7
:1015700080913F03806180933F038FEF80933C0312
:1015800010924203109241031092400310924403C0
:1015900008958091C10083FF0CC1809113038823BB
:1015A00009F407C180913F0382FF34C08091130387
:1015B000882381F180E190E09F938F9380913E0397
:1015C000992724E0880F991F2A95E1F78F5E9E4F97
:1015D0009F938F9381E090E09F938F938EE393E0AE
:1015E0009F938F9382E08F9383E08F9381E48F9317
:1015F0000E94F8088FEF80933E0380913F038B7F1A
:1016000080933F038DB79EB70B960FB6F8949EBF9D
:101610000FBE8DBF80913D038823F1F080911303AD
:101620008823D1F081E090E09F938F938DE393E046
:101630009F938F9381E08F9383E08F9382E48F93C6
:101640000E94F80810923D038DB79EB707960FB61B
:10165000F8949EBF0FBE8DBF80911103909112032D
:10166000892B41F080916804909169040E946C0C70
:10167000882321F480913F0381FF2DC080911303C3
:10168000882349F10E94160582E490E09F938F938E
:1016900082EC93E09F938F9381E08F9383E08F930D
:1016A00084E48F930E94F8088091110390911203B3
:1016B0000E94630C909369048093680480913F03B7
:1016C0008D7F80933F038DB79EB707960FB6F89432
:1016D0009EBF0FBE8DBF80913F0384FF21C08091CC
:1016E00013038823E9F08BE090E09F938F938FEAB8
:1016F00093E09F938F9381E08F9383E08F9387E4B0
:101700008F930E94F80880913F038F7E80933F0360
:101710008DB79EB707960FB6F8949EBF0FBE8DBFCC
:1017200080913F0383FF20C0809113038823E1F061
:1017300082E090E09F938F9381E794E09F938F9353
:1017400081E08F938F938BE48F930E94F8088091B0
:101750003F03877F80933F038DB79EB707960FB6F1
:10176000F8949EBF0FBE8DBF80913F0380FF21C0C4
:10177000809113038823E9F08AE090E09F938F9390
:1017800085EA93E09F938F9381E08F9383E08F931B
:1017900086E58F930E94F80880913F038E7F8093A7
:1017A0003F038DB79EB707960FB6F8949EBF0FBE46
:1017B0008DBF08951F93CF93DF93EC0110E08881D4
:1017C000882369F0FE01E10FF11D1F5F80810E94F7
:1017D0002007FE01E10FF11D8081882399F7DF9139
:1017E000CF911F910895229A2A9884B58C7084BD58
:1017F00085B5837385BD82E085BD16BC80916E0082
:10180000897F80936E0080916E00816080936E006E
:1018100008951F920F920FB60F9211242F933F93AA
:101820004F938F939F9386B5855686BD2091000177
:101830003091010137FF02C02A980EC080914F03FA
:101840009091500301969093500380934F0341E091
:101850008C37940730F02A9A1092500310924F035D
:1018600006C0265F3F4F8217930708F02A988091A1
:101870004E03815080934E038823D9F48AE08093ED
:101880004E0380914C0390914D03019690934D032C
:1018900080934C0380914A0390914B03892B49F02C
:1018A00080914A0390914B03019790934B0380934F
:1018B0004A039F918F914F913F912F910F900FBEAF
:1018C0000F901F90189520914C0330914D03280FD5
:1018D000391FC9010197089520914C0330914D03A0
:1018E000821B930B892F990F990B80780895CF93C2
:1018F000DF930E94630CEC01CE010E946C0C8823E4
:10190000D9F3DF91CF91089580937C0080917A0084
:10191000806180937A0080917A00806480937A005D
:1019200080917A0084FFFCCF8091780090917900BB
:10193000089587B1807F87B988B1807F88B98AB1DF
:1019400080668AB98BB18F798BB910927C008091B7
:101950007A00877980937A0080917A0087698093F2
:101960007A0010927C0080917A00806480937A00E3
:1019700088B18C6088B980E29EE40197F1F782E03B
:101980000E94840C895E934048F083E00E94840C9E
:10199000895E934018F01092510303C081E0809358
:1019A000510388B1837F88B908959FB7F89484B1B3
:1019B0008F7C84B985B1806385B987B18F7C87B905
:1019C00088B18F7C88B910925803109257031092F7
:1019D000540310925903109256031092550310921B
:1019E000530310925A038091BC008F7D8093BC00FA
:1019F0008091BC0085648093BC0080E58093BA0030
:101A00008091BC00856D8093BC001092730485E1C9
:101A10008093740481E08093750482E0809376045F
:101A20009FBF08951F920F920FB60F9211242F930C
:101A30003F938F939F93AF93BF93EF93FF938091C7
:101A4000B9009927887F907080389105A9F0813876
:101A500091053CF4009709F42AC18036910551F0B4
:101A600028C1883A910509F4E9C0883B910509F439
:101A7000F5C01FC18FEFDFC03091BB002091530331
:101A80002F3F09F08CC0832F99278230910569F18F
:101A9000833091051CF4019741F070C083309105AB
:101AA00009F44BC0049789F069C083E794E09093F0
:101AB00058038093570384E0809359031092560390
:101AC0001092550310925A0365C08AE694E09093F1
:101AD00058038093570323E02093590390935603B0
:101AE0008093550320935A0355C081E894E0909366
:101AF00058038093570386E080935903109256034E
:101B00001092550310925A03809128039091290353
:101B100090938204809381048091260390912703FF
:101B200090938404809383048091240390912503EF
:101B300090938604809385042DC081E794E0909370
:101B400058038093570382E0809359038DE694E015
:101B5000909356038093550384E080935A038091B9
:101B6000000190910101909372048093710410928E
:101B7000030110920201209352030CC010925603ED
:101B80001092550310925A03109258031092570363
:101B9000109259031092530330935B038AC09091C3
:101BA000530380915A03981768F480915303E82FE8
:101BB000FF27E958FB4F308380915B03830F8093AD
:101BC0005B0336C09091530380915A03981781F5B7
:101BD00080915B03831719F580915503909156030B
:101BE000892B99F030E080915A03381770F4E32F75
:101BF000FF27A0915503B0915603AE0FBF1FE958C0
:101C0000FB4F80818C933F5FEECF809102049091D7
:101C100003040196909303048093020409C0809109
:101C200000049091010401969093010480930004B4
:101C3000809153038F5F809353033BC010925403F2
:101C400010925B03E0915703F0915803309721F015
:101C500080915903823070F430E011C0E091570355
:101C6000F0915803309789F0909154038091590373
:101C7000981758F480915403E80FF11D308180913A
:101C80005B03830F80935B030AC0909154038091A0
:101C90005903981719F430915B0301C030E080912B
:101CA00054038F5F809354033093BB0002C085EDD3
:101CB00001C085EC8093BC00FF91EF91BF91AF9183
:101CC0009F918F913F912F910F900FBE0F901F907A
:101CD0001895579A5F9808955058192EA4D101D09D
:101CE00054C1BA176207730784079507B1F188F4E6
:101CF0000EF410940B2EBA2FA02D062E622F202D3D
:101D0000072E732F302D082E842F402D092E952F4E
:101D1000502DFF275523B9F0591B49F0573E98F035
:101D2000469537952795A795F0405395C9F776F0D6
:101D3000BA0F621F731F841F30F4879577956795DC
:101D4000B795F040939517FA0F2E0895BF1BBB2748
:101D5000BA0B620B730B840BF6CFDEF690C1AA2789
:101D600097FDA160AF939F775FE340E86130710515
:101D70008407950720F00E94DD0FAF9108959F938F
:101D80008F937F936F93E8E6F0E00E94E00F2F912E
:101D90003F914F915F919F938F937F936F939FE3B9
:101DA00080E87727662750680E946D0E0E94CC104D
:101DB0002F913F914F915F910E9471105FE349EC29
:101DC0003FE02BED90680E946D0EAF91A0FD9068F2
:101DD0000895552319F0992351F018C09923A1F0C3
:101DE00097FB6BED7FE089EC9FE397F9089555230E
:101DF00059F02AF46BED7FE089E490E408956627BA
:101E000077278827992708950C94DD0F1F931127B2
:101E100097FD116057FD12600E94220F0E940E1163
:101E200011FF08C02BED3FE049E450E410FD50687D
:101E30000E946D0E1F91089550E449EC3FE02BED98
:101E40006ED080C0F0D001D0A0C0552359F09923A6
:101E500069F09F575F57951B33F442F4903811F4A3
:101E6000915805C0AAC091589F3F09F408C1BB27EB
:101E7000112462177307840730F4660F771F881FD9
:101E8000BB1F915098F311D00F920FD00F920DD02D
:101E9000A0E82617370748071B0609F0A048BA2F05
:101EA000602D7F918F9100240895A0E8002462178F
:101EB00073078407B10528F0621B730B840BB1090B
:101EC0000A2A660F771F881FBB1FA69581F7089502
:101ED00097FBB5D09F3738F0FEE9F91B982F872F75
:101EE000762F6B2F05C0C8C0969587957795679517
:101EF000F150D0F73EF490958095709561957F4FA5
:101F00008F4F9F4F0895E89403C097FB0EF4F3DFC3
:101F1000B62F672F782F892F9EE9002436C05F7770
:101F2000552319F444230AF048C02F933F934F934D
:101F30005F9388DF55274427A4D05F914F913F914D
:101F40002F91CFC01F939F7750EC49E43FE02BEDDA
:101F5000C4DE10E89F775FE349EC3FE02BED6217AA
:101F600073078407950720F050EC49E4B6DE11278B
:101F700051D19068EAE8F0E023D091271F910895AD
:101F80009A95BB0F661F771F881F11249923A1F014
:101F90008823B2F79F3F59F0BB0F48F421F400208B
:101FA00011F460FF04C06F5F7F4F8F4F9F4F881FFA
:101FB0009795879597F908955FC09FEF80EC0895F6
:101FC000FF92EF92DF92CF92BF926B017C01B590AE
:101FD00016D0B590BB2069F09F938F937F936F933A
:101FE000B601C7010CD02F913F914F915F910E9494
:101FF000220FBF90CF90DF90EF90FF9008953DD1DA
:1020000002C09601A701EF93FF930E947110FF9108
:10201000EF9133D1EF93FF930E946D0EFF91EF91FB
:10202000BA9479F70895052E092607FA440F551F2B
:102030005F3F79F0AA27A51708F051E04795880F70
:10204000991F9F3F31F0BB27B91708F091E08795A2
:1020500008959F919F911124B0CF97FB880F991FEE
:102060009F3F31F0BB27B91708F091E0879508959D
:102070009F919F911124A1CF6627772788279927C1
:102080000895EBDFCF93DF93D52FC42F5527442737
:10209000332722279923D9F09F37C8F0F92F75DF0E
:1020A000592F482F372F262FF63968F411DF2DDFEF
:1020B000C030CD0721F06993799389939993905813
:1020C000DF91CF910ACE9927882777276627C030DE
:1020D000CD0721F02993399349935993DF91CF91FB
:1020E00054CFA1DF01D051CF992339F0552329F0E6
:1020F0009F575F57950F13F49AF1C1CF91589F3FA7
:10210000E1F3629FA12D0F92BB27639FA00DB11D2C
:10211000EE27729FA00DB11DEE1FAF93AA27649FFB
:10212000B00DE11D739FB00DE11DAA1F6627829FB0
:10213000B00DE11DA61F5527749FE00DA11D551F71
:10214000839FE00DA11D561F849FA00D511D852F5B
:102150007A2F6E2F1F900F9088231AF4939539F4DD
:102160002CCF000C111CBB1F661F771F881F012876
:1021700008959F939F77993358F050E449EC3FE0DE
:102180002BEDCDDE5FEB49EC3FE02BEDA6DDDADE9B
:102190005F9150789527089597FD0FCF992309F403
:1021A0000895482F5ADFF92FFF57F5959F1B9F1B66
:1021B000FF93EBDEFF92EF92DF92CF92BF92AF924E
:1021C0009F928F926B017C014058479533272227BD
:1021D00040685FE3B601C70149015A010E94220F1E
:1021E0009401A5010E946D0E4FEF5FEF53D09B014C
:1021F000AC0182169306A406B50661F78F909F90F6
:10220000AF90BF90CF90DF90EF90FF905F9125DF70
:10221000950FBBCE9B01AC010C9471101F930F93D3
:102220000027192F10789F775FE340E86130710530
:102230008407950718F000680E944211912B6F9354
:102240007F938F939F930E940A11E0EBF0E0B8DE3A
:102250005F914F913F912F910E947110002351F097
:102260002BED3FE049EC5FE300E8902717FD506855
:102270000E946D0E0F911F910895559145913591D2
:10228000259108959B01AC019FE380E8772766279D
:102290000C94220FE2DE992359F0AA27940FA51F70
:1022A00043F032F04FEF50E09417A50714F46DCED1
:1022B000E3CE0EF006C000C09FEF80E870E060E063
:1022C00008959FE780E870E060E0089597FB092E8D
:1022D00005260ED057FD04D014D00AD0001C38F4C7
:1022E00050954095309521953F4F4F4F5F4F089542
:1022F000F6F790958095709561957F4F8F4F9F4F22
:102300000895A1E21A2EAA1BBB1BFD010DC0AA1F36
:10231000BB1FEE1FFF1FA217B307E407F50720F04E
:10232000A21BB30BE40BF50B661F771F881F991FC9
:102330001A9469F760957095809590959B01AC0112
:10234000BD01CF01089509D001921A94E1F70895D3
:1023500001900BD01A94E1F70895F999FECFB2BD20
:10236000A1BDF89A119600B40895F999FECFB2BDB7
:10237000A1BD00BC11960FB6F894FA9AF99A0FBE57
:022380000895BE
:10238200FFFF01024143432070726573656E740A58
:10239200004D61676E657420582020202020202087
:1023A200204D61676E657420592020202020202056
:1023B200204D61676E6574205A2020202020202045
:1023C200205261774D61676E65742058202020206D
:1023D200205261774D61676E65742059202020205C
:1023E200205261774D61676E6574205A202020204B
:1023F200204174746974756465204E69636B202092
:1024020020417474697475646520526F6C6C20206D
:10241200204D61676E65742058204F66667365743F
:10242200204D61676E657420582052616E67652089
:10243200204D61676E65742059204F66667365741E
:10244200204D61676E657420592052616E67652068
:10245200204D61676E6574205A204F6666736574FD
:10246200204D61676E6574205A2052616E67652047
:102472002043616C73746174652020202020202029
:102482002048656164696E6720202020202020207A
:10249200205573657230202020202020202020200B
:1024A20020557365723120202020202020202020FA
:1024B200204163632058202020202020202020203B
:1024C200204163632059202020202020202020202A
:1024D20020416363205A2020202020202020202019
:1024E2002052617741636320582020202020202041
:1024F2002052617741636320592020202020202030
:1025020020526177416363205A202020202020201E
:10251200204163632058204F666673657420202033
:10252200204163632059204F666673657420202022
:1025320020416363205A204F666673657420202011
:1025420020416E616C6F67323720202020202020CE
:1025520020416E616C6F67323820202020202020BD
:1025620020416E616C6F67323920202020202020AC
:1025720020493243204572726F7220202020202091
:1025820020493243204F6B617920202020202020D7
:0425920020F401012F
:00000001FF
/tags/V0.21b/License.txt
0,0 → 1,56
/*#######################################################################################
MK3Mag 3D-Magnet sensor
!!! THIS IS NOT FREE SOFTWARE !!!
#######################################################################################*/
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Copyright (c) 05.2008 Holger Buss
// + Thanks to Ilja Fähnrich (P_Latzhalter)
// + Nur für den privaten Gebrauch
// + www.MikroKopter.com
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Die Portierung der Software (oder Teile davon) auf andere Systeme (ausser der Hardware von www.mikrokopter.de) ist nur
// + mit unserer Zustimmung zulässig
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Es gilt für das gesamte Projekt (Hardware, Software, Binärfiles, Sourcecode und Dokumentation),
// + dass eine Nutzung (auch auszugsweise) nur für den privaten (nicht-kommerziellen) Gebrauch zulässig ist.
// + AUSNAHME: Ein bei www.mikrokopter.de erworbener vorbestückter MK3Mag darf als Baugruppe auch in kommerziellen Systemen verbaut werden
// + Im Zweifelsfall bitte anfragen bei: info@mikrokopter.de
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Werden Teile des Quellcodes (mit oder ohne Modifikation) weiterverwendet oder veröffentlicht,
// + unterliegen sie auch diesen Nutzungsbedingungen und diese Nutzungsbedingungen incl. Copyright müssen dann beiliegen
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Sollte die Software (auch auszugesweise) oder sonstige Informationen des MikroKopter-Projekts
// + auf anderen Webseiten oder sonstigen Medien veröffentlicht werden, muss unsere Webseite "http://www.mikrokopter.de"
// + eindeutig als Ursprung verlinkt werden
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Keine Gewähr auf Fehlerfreiheit, Vollständigkeit oder Funktion
// + Benutzung auf eigene Gefahr
// + Wir übernehmen keinerlei Haftung für direkte oder indirekte Personen- oder Sachschäden
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Die Funktion printf_P() unterliegt ihrer eigenen Lizenz und ist hiervon nicht betroffen
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Redistributions of source code (with or without modifications) must retain the above copyright notice,
// + this list of conditions and the following disclaimer.
// + * PORTING this software (or parts of it) to systems (other than hardware from www.mikrokopter.de) is NOT allowed
// + * Neither the name of the copyright holders nor the names of contributors may be used to endorse or promote products derived
// + from this software without specific prior written permission.
// + * The use of this project (hardware, software, binary files, sources and documentation) is only permittet
// + for non-commercial use (directly or indirectly)
// + Commercial use (for excample: selling of MikroKopters, selling of PCBs, assembly, ...) is only permitted
// + with our written permission
// + Exception: A preassembled MK3Mag, purchased from www.mikrokopter.de may be used as a part of commercial systems
// + In case of doubt please contact: info@MikroKopter.de
// + * If sources or documentations are redistributet on other webpages, our webpage (http://www.MikroKopter.de) must be
// + clearly linked as origin
// + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// + POSSIBILITY OF SUCH DAMAGE.
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
/tags/V0.21b/analog.c
0,0 → 1,117
/*#######################################################################################
MK3Mag 3D-Magnet sensor
!!! THIS IS NOT FREE SOFTWARE !!!
#######################################################################################*/
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Copyright (c) 05.2008 Holger Buss
// + Thanks to Ilja Fähnrich (P_Latzhalter)
// + Nur für den privaten Gebrauch
// + www.MikroKopter.com
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Die Portierung der Software (oder Teile davon) auf andere Systeme (ausser der Hardware von www.mikrokopter.de) ist nur
// + mit unserer Zustimmung zulässig
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Es gilt für das gesamte Projekt (Hardware, Software, Binärfiles, Sourcecode und Dokumentation),
// + dass eine Nutzung (auch auszugsweise) nur für den privaten (nicht-kommerziellen) Gebrauch zulässig ist.
// + AUSNAHME: Ein bei www.mikrokopter.de erworbener vorbestückter MK3Mag darf als Baugruppe auch in kommerziellen Systemen verbaut werden
// + Im Zweifelsfall bitte anfragen bei: info@mikrokopter.de
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Werden Teile des Quellcodes (mit oder ohne Modifikation) weiterverwendet oder veröffentlicht,
// + unterliegen sie auch diesen Nutzungsbedingungen und diese Nutzungsbedingungen incl. Copyright müssen dann beiliegen
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Sollte die Software (auch auszugesweise) oder sonstige Informationen des MikroKopter-Projekts
// + auf anderen Webseiten oder sonstigen Medien veröffentlicht werden, muss unsere Webseite "http://www.mikrokopter.de"
// + eindeutig als Ursprung verlinkt werden
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Keine Gewähr auf Fehlerfreiheit, Vollständigkeit oder Funktion
// + Benutzung auf eigene Gefahr
// + Wir übernehmen keinerlei Haftung für direkte oder indirekte Personen- oder Sachschäden
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Die Funktion printf_P() unterliegt ihrer eigenen Lizenz und ist hiervon nicht betroffen
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Redistributions of source code (with or without modifications) must retain the above copyright notice,
// + this list of conditions and the following disclaimer.
// + * PORTING this software (or parts of it) to systems (other than hardware from www.mikrokopter.de) is NOT allowed
// + * Neither the name of the copyright holders nor the names of contributors may be used to endorse or promote products derived
// + from this software without specific prior written permission.
// + * The use of this project (hardware, software, binary files, sources and documentation) is only permittet
// + for non-commercial use (directly or indirectly)
// + Commercial use (for excample: selling of MikroKopters, selling of PCBs, assembly, ...) is only permitted
// + with our written permission
// + Exception: A preassembled MK3Mag, purchased from www.mikrokopter.de may be used as a part of commercial systems
// + In case of doubt please contact: info@MikroKopter.de
// + * If sources or documentations are redistributet on other webpages, our webpage (http://www.MikroKopter.de) must be
// + clearly linked as origin
// + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// + POSSIBILITY OF SUCH DAMAGE.
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#include <util/delay.h>
#include "analog.h"
 
uint8_t AccPresent = 0;
 
void ADC_Init(void)
{
// The analog inputs have a VREF of 5V and a resolution of 10 bit (0...1024 counts)
// i.e. 4.88mV/Count
 
// set PortC 0,1,2,3 as input
DDRC &= ~((1<<DDC3)|(1<<DDC2)|(1<<DDC1)|(1<<DDC0));
// set PortC 0,1,2,3 as tri state
PORTC &= ~((1<<PORTC3)|(1<<PORTC2)|(1<<PORTC1)|(1<<PORTC0));
 
// port PD5 and PD6 control the current direction of the test coils of the sensors
DDRD |= ((1<<DDD5)|(1<<DDD6));
FLIP_LOW;
 
// disable internal reference voltage and right adjust bits in ADCW
ADMUX = 0x00;
// clear start conversion bit (ADSC = 0)
// disable ADC Auto Trigger Enable (ADATE = 0)
// disable interrupt (ADIE = 0)
ADCSRA &= ~((1<<ADSC)|(1<<ADATE)|(1<<ADIE));
// Enable ADC (ADEN = 1) with SYSCLK/128 (ADPS2 = 1, ADPS1 = 1, ADPS0 = 1) and clear ready flag (ADIF = 1)
ADCSRA |= ((1<<ADEN)|(1<<ADIF)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0));
ADMUX = 0x00; // select ADC0
ADCSRA |= (1<<ADSC); // start conversion
 
 
// Check if acceleration sensor is present
// The output of the LIS3L02AL (MK3MAG V1.0) and the LIS344ALH (MK3MAG V1.1) is Vdd/5 +/- 10% per 1g.
// The Vdd is 3.0V at this board therefore the sensitivity is 0.6V/g +/-10% that corresponds to 123 counts.
// The offsets at 0g is VDD/2 (1.5V) that is 307 counts.
// that yields to an ADC range of 184 to 430 counts.
 
// pullup PC2(AccX) and PC3 (AccY)
PORTC |= ((1<<PORTC3)|(1<<PORTC2));
_delay_ms(10.0);
// if ADC2 and ADC 3 is larger than 1000 counts (4.88V) no load is at the pins
if((ADC_GetValue(ADC2) > 1000) && (ADC_GetValue(ADC3) > 1000)) AccPresent = 0;
else AccPresent = 1;
// set port back to tristate
PORTC &= ~((1<<PORTC3)|(1<<PORTC2));
}
 
 
uint16_t ADC_GetValue(ADChannel_t channel)
{
uint16_t value = 0;
ADMUX = channel; // set muxer bits
ADCSRA |= (1<<ADIF); // clear ready-flag
ADCSRA |= (1<<ADSC); // start conversion
while (((ADCSRA & (1<<ADIF)) == 0)); // wait for end of conversion
value = ADCW; // read adc result
return(value);
}
 
 
 
/tags/V0.21b/analog.h
0,0 → 1,39
#ifndef _ANALOG_H_
#define _ANALOG_H_
 
#include <inttypes.h>
#include <avr/io.h>
 
#define FLIP_HIGH PORTD |= ((1<<PORTD5)|(1<<PORTD6))
#define FLIP_LOW PORTD &= ~((1<<PORTD5)|(1<<PORTD6))
 
typedef enum
{
ADC0 = 0,
ADC1 = 1,
ADC2 = 2,
ADC3 = 3,
ADC4 = 4,
ADC5 = 5,
ADC6 = 6,
ADC7 = 7,
REF1V1 = 14,
AGND = 15
} ADChannel_t;
 
 
#define MAG_X ADC0
#define MAG_Y ADC1
#define MAG_Z ADC7
#define ACC_X ADC2
#define ACC_Y ADC3
#define ACC_Z ADC6
 
 
extern uint8_t AccPresent;
 
void ADC_Init(void);
uint16_t ADC_GetValue(ADChannel_t channel);
 
#endif // _ANALOG_H_
 
/tags/V0.21b/led.c
0,0 → 1,67
/*#######################################################################################
MK3Mag 3D-Magnet sensor
!!! THIS IS NOT FREE SOFTWARE !!!
#######################################################################################*/
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Copyright (c) 05.2008 Holger Buss
// + Thanks to Ilja Fähnrich (P_Latzhalter)
// + Nur für den privaten Gebrauch
// + www.MikroKopter.com
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Die Portierung der Software (oder Teile davon) auf andere Systeme (ausser der Hardware von www.mikrokopter.de) ist nur
// + mit unserer Zustimmung zulässig
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Es gilt für das gesamte Projekt (Hardware, Software, Binärfiles, Sourcecode und Dokumentation),
// + dass eine Nutzung (auch auszugsweise) nur für den privaten (nicht-kommerziellen) Gebrauch zulässig ist.
// + AUSNAHME: Ein bei www.mikrokopter.de erworbener vorbestückter MK3Mag darf als Baugruppe auch in kommerziellen Systemen verbaut werden
// + Im Zweifelsfall bitte anfragen bei: info@mikrokopter.de
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Werden Teile des Quellcodes (mit oder ohne Modifikation) weiterverwendet oder veröffentlicht,
// + unterliegen sie auch diesen Nutzungsbedingungen und diese Nutzungsbedingungen incl. Copyright müssen dann beiliegen
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Sollte die Software (auch auszugesweise) oder sonstige Informationen des MikroKopter-Projekts
// + auf anderen Webseiten oder sonstigen Medien veröffentlicht werden, muss unsere Webseite "http://www.mikrokopter.de"
// + eindeutig als Ursprung verlinkt werden
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Keine Gewähr auf Fehlerfreiheit, Vollständigkeit oder Funktion
// + Benutzung auf eigene Gefahr
// + Wir übernehmen keinerlei Haftung für direkte oder indirekte Personen- oder Sachschäden
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Die Funktion printf_P() unterliegt ihrer eigenen Lizenz und ist hiervon nicht betroffen
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Redistributions of source code (with or without modifications) must retain the above copyright notice,
// + this list of conditions and the following disclaimer.
// + * PORTING this software (or parts of it) to systems (other than hardware from www.mikrokopter.de) is NOT allowed
// + * Neither the name of the copyright holders nor the names of contributors may be used to endorse or promote products derived
// + from this software without specific prior written permission.
// + * The use of this project (hardware, software, binary files, sources and documentation) is only permittet
// + for non-commercial use (directly or indirectly)
// + Commercial use (for excample: selling of MikroKopters, selling of PCBs, assembly, ...) is only permitted
// + with our written permission
// + Exception: A preassembled MK3Mag, purchased from www.mikrokopter.de may be used as a part of commercial systems
// + In case of doubt please contact: info@MikroKopter.de
// + * If sources or documentations are redistributet on other webpages, our webpage (http://www.MikroKopter.de) must be
// + clearly linked as origin
// + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// + POSSIBILITY OF SUCH DAMAGE.
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#include "led.h"
 
 
void LED_Init(void)
{
// Set PD7 as output
DDRD |= (1<<DDD7);
// set port pon to GND
PORTD &= ~((1<<PORTD7));
}
 
/tags/V0.21b/led.h
0,0 → 1,12
#ifndef _LED_H_
#define _LED_H_
 
#include <avr/io.h>
 
#define LED_GRN_ON PORTD |= (1<<PORTD7)
#define LED_GRN_OFF PORTD &= ~(1<<PORTD7)
#define LED_GRN_TOGGLE PORTD ^= (1<<PORTD7)
 
void LED_Init(void);
 
#endif //_LED_H_
/tags/V0.21b/main.c
0,0 → 1,492
/*#######################################################################################
MK3Mag 3D-Magnet sensor
!!! THIS IS NOT FREE SOFTWARE !!!
#######################################################################################*/
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Copyright (c) 05.2008 Holger Buss
// + Thanks to Ilja Fähnrich (P_Latzhalter)
// + Nur für den privaten Gebrauch
// + www.MikroKopter.com
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Die Portierung der Software (oder Teile davon) auf andere Systeme (ausser der Hardware von www.mikrokopter.de) ist nur
// + mit unserer Zustimmung zulässig
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Es gilt für das gesamte Projekt (Hardware, Software, Binärfiles, Sourcecode und Dokumentation),
// + dass eine Nutzung (auch auszugsweise) nur für den privaten (nicht-kommerziellen) Gebrauch zulässig ist.
// + AUSNAHME: Ein bei www.mikrokopter.de erworbener vorbestückter MK3Mag darf als Baugruppe auch in kommerziellen Systemen verbaut werden
// + Im Zweifelsfall bitte anfragen bei: info@mikrokopter.de
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Werden Teile des Quellcodes (mit oder ohne Modifikation) weiterverwendet oder veröffentlicht,
// + unterliegen sie auch diesen Nutzungsbedingungen und diese Nutzungsbedingungen incl. Copyright müssen dann beiliegen
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Sollte die Software (auch auszugesweise) oder sonstige Informationen des MikroKopter-Projekts
// + auf anderen Webseiten oder sonstigen Medien veröffentlicht werden, muss unsere Webseite "http://www.mikrokopter.de"
// + eindeutig als Ursprung verlinkt werden
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Keine Gewähr auf Fehlerfreiheit, Vollständigkeit oder Funktion
// + Benutzung auf eigene Gefahr
// + Wir übernehmen keinerlei Haftung für direkte oder indirekte Personen- oder Sachschäden
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Die Funktion printf_P() unterliegt ihrer eigenen Lizenz und ist hiervon nicht betroffen
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Redistributions of source code (with or without modifications) must retain the above copyright notice,
// + this list of conditions and the following disclaimer.
// + * PORTING this software (or parts of it) to systems (other than hardware from www.mikrokopter.de) is NOT allowed
// + * Neither the name of the copyright holders nor the names of contributors may be used to endorse or promote products derived
// + from this software without specific prior written permission.
// + * The use of this project (hardware, software, binary files, sources and documentation) is only permittet
// + for non-commercial use (directly or indirectly)
// + Commercial use (for excample: selling of MikroKopters, selling of PCBs, assembly, ...) is only permitted
// + with our written permission
// + Exception: A preassembled MK3Mag, purchased from www.mikrokopter.de may be used as a part of commercial systems
// + In case of doubt please contact: info@MikroKopter.de
// + * If sources or documentations are redistributet on other webpages, our webpage (http://www.MikroKopter.de) must be
// + clearly linked as origin
// + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// + POSSIBILITY OF SUCH DAMAGE.
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#include <avr/interrupt.h>
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
 
#include "main.h"
#include "timer0.h"
#include "twislave.h"
#include "led.h"
#include "analog.h"
#include "uart.h"
 
#define CALIBRATION_VERSION 1
 
AttitudeSource_t AttitudeSource = ATTITUDE_SOURCE_ACC;
Orientation_t Orientation = ORIENTATION_FC;
 
uint16_t Led_Timer = 0;
 
typedef struct
{
int16_t Range;
int16_t Offset;
} Scaling_t;
 
typedef struct
{
Scaling_t MagX;
Scaling_t MagY;
Scaling_t MagZ;
Scaling_t AccX;
Scaling_t AccY;
Scaling_t AccZ;
unsigned char Version;
} Calibration_t;
 
Calibration_t eeCalibration EEMEM; // calibration data in EEProm
Calibration_t Calibration; // calibration data in RAM
 
// magnet sensor variable
int16_t RawMagnet1a, RawMagnet1b; // raw magnet sensor data
int16_t RawMagnet2a, RawMagnet2b;
int16_t RawMagnet3a, RawMagnet3b;
int16_t UncalMagX, UncalMagY, UncalMagZ; // sensor signal difference without Scaling
int16_t MagX = 0, MagY = 0, MagZ = 0; // rescaled magnetic field readings
 
// acceleration sensor variables
int16_t RawAccX = 0, RawAccY = 0, RawAccZ = 0; // raw acceleration readings
int16_t AccX = 0, AccY = 0, AccZ = 0; // rescaled acceleration readings
int16_t AccAttitudeNick = 0, AccAttitudeRoll = 0; // nick and roll angle from acc
 
int16_t Heading = -1; // the current compass heading in deg
 
 
void CalcFields(void)
{
UncalMagX = (RawMagnet1a - RawMagnet1b);
UncalMagY = (RawMagnet3a - RawMagnet3b);
UncalMagZ = (RawMagnet2a - RawMagnet2b);
 
if(Calibration.MagX.Range != 0) MagX = (1024L * (int32_t)(UncalMagX - Calibration.MagX.Offset)) / (Calibration.MagX.Range);
else MagX = 0;
if(Calibration.MagY.Range != 0) MagY = (1024L * (int32_t)(UncalMagY - Calibration.MagY.Offset)) / (Calibration.MagY.Range);
else MagY = 0;
if(Calibration.MagY.Range != 0) MagZ = (1024L * (int32_t)(UncalMagZ - Calibration.MagZ.Offset)) / (Calibration.MagZ.Range);
else MagZ = 0;
 
if(AccPresent)
{
AccX = (RawAccX - Calibration.AccX.Offset);
AccY = (RawAccY - Calibration.AccY.Offset);
AccZ = (Calibration.AccZ.Offset - RawAccZ);
#if (BOARD == 10) // the hardware 1.0 has the LIS3L02AL
// acc mode assumes orientation like FC
if(AccX > 136) AccAttitudeNick = -800;
else
if(AccX < -136) AccAttitudeNick = 800;
else AccAttitudeNick = (int16_t)(-1800.0 * asin((double) AccX / 138.0) / M_PI);
 
 
if(AccY > 136) AccAttitudeRoll = 800;
else
if(AccY < -136) AccAttitudeRoll = -800;
else AccAttitudeRoll = (int16_t)( 1800.0 * asin((double) AccY / 138.0) / M_PI);
 
#else // the hardware 1.1 has the LIS344ALH with a different axis definition (X -> -Y, Y -> X, Z -> Z)
// acc mode assumes orientation like FC
if(AccY > 136) AccAttitudeNick = 800;
else
if(AccY < -136) AccAttitudeNick = -800;
else AccAttitudeNick = (int16_t)( 1800.0 * asin((double) AccY / 138.0) / M_PI);
 
 
if(AccX > 136) AccAttitudeRoll = 800;
else
if(AccX < -136) AccAttitudeRoll = -800;
else AccAttitudeRoll = (int16_t)( 1800.0 * asin((double) AccX / 138.0) / M_PI);
#endif
}
}
 
 
void CalcHeading(void)
{
double nick_rad, roll_rad, Hx, Hy, Cx = 0.0, Cy = 0.0, Cz = 0.0;
int16_t nick, roll;
int16_t heading = -1;
 
// blink code for normal operation
if(CheckDelay(Led_Timer))
{
if(Calibration.Version != CALIBRATION_VERSION) LED_GRN_TOGGLE;
else LED_GRN_ON;
Led_Timer = SetDelay(150);
}
switch(Orientation)
{
case ORIENTATION_NC:
Cx = MagX;
Cy = MagY;
Cz = MagZ;
break;
 
case ORIENTATION_FC:
// rotation of 90 deg compared to NC setup
Cx = MagY;
Cy = -MagX;
Cz = MagZ;
break;
}
 
// calculate nick and roll angle in rad
switch(AttitudeSource)
{
case ATTITUDE_SOURCE_I2C:
cli(); // stop interrupts
nick = I2C_WriteAttitude.Nick;
roll = I2C_WriteAttitude.Roll;
sei(); // start interrupts
break;
case ATTITUDE_SOURCE_UART:
cli(); // stop interrupts
nick = ExternData.Attitude[NICK];
roll = ExternData.Attitude[ROLL];
sei(); // start interrupts
break;
case ATTITUDE_SOURCE_ACC:
nick = AccAttitudeNick;
roll = AccAttitudeRoll;
break;
default:
nick = 0;
roll = 0;
break;
}
 
nick_rad = ((double)nick) * M_PI / (double)(1800.0);
roll_rad = ((double)roll) * M_PI / (double)(1800.0);
 
// calculate attitude correction
Hx = Cx * cos(nick_rad) - Cz * sin(nick_rad);
Hy = Cy * cos(roll_rad) + Cz * sin(roll_rad);
 
DebugOut.Analog[27] = (int16_t)Hx;
DebugOut.Analog[28] = (int16_t)Hy;
 
// calculate Heading
heading = (int16_t)((180.0 * atan2(Hy, Hx)) / M_PI);
// atan2 returns angular range from -180 deg to 180 deg in counter clockwise notation
// but the compass course is defined in a range from 0 deg to 360 deg clockwise notation.
if (heading < 0) heading = -heading;
else heading = 360 - heading;
 
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
if(Calibration.Version != CALIBRATION_VERSION) heading = -1; // Version of the calibration Data does not match
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
cli(); // stop interrupts
if(abs(heading) < 361) Heading = heading;
else (Heading = -1);
sei(); // start interrupts
 
}
 
void Calibrate(void)
{
uint8_t cal;
static uint8_t calold = 0;
static int16_t Xmin = 0, Xmax = 0, Ymin = 0, Ymax = 0, Zmin = 0, Zmax = 0;
static uint8_t blinkcount = 0;
static uint8_t invert_blinking = 0;
 
// check both sources of communication for calibration request
if(I2C_WriteCal.CalByte) cal = I2C_WriteCal.CalByte;
else cal = ExternData.CalState;
 
 
if(cal > 5) cal = 0;
// blink code for current calibration state
if(cal)
{
if(CheckDelay(Led_Timer) || (cal != calold))
{
if(blinkcount & 0x01) if(invert_blinking) LED_GRN_ON; else LED_GRN_OFF;
else if(invert_blinking) LED_GRN_OFF; else LED_GRN_ON;
 
// end of blinkcount sequence
if((blinkcount + 1 ) >= (2 * cal))
{
blinkcount = 0;
Led_Timer = SetDelay(1500);
}
else
{
blinkcount++;
Led_Timer = SetDelay(100);
}
}
}
else
{
if(invert_blinking) LED_GRN_ON; else LED_GRN_OFF;
}
// calibration state machine
switch(cal)
{
case 1: // 1st step of calibration
// initialize ranges
// used to change the orientation of the MK3MAG in the horizontal plane
Xmin = 10000;
Xmax = -10000;
Ymin = 10000;
Ymax = -10000;
Zmin = 10000;
Zmax = -10000;
Calibration.AccX.Offset = RawAccX;
Calibration.AccY.Offset = RawAccY;
Calibration.AccZ.Offset = RawAccZ;
invert_blinking = 0;
break;
 
case 2: // 2nd step of calibration
// find Min and Max of the X- and Y-Sensors during rotation in the horizontal plane
if(UncalMagX < Xmin) Xmin = UncalMagX;
if(UncalMagX > Xmax) Xmax = UncalMagX;
if(UncalMagY < Ymin) Ymin = UncalMagY;
if(UncalMagY > Ymax) Ymax = UncalMagY;
invert_blinking = 1;
break;
 
case 3: // 3rd step of calibration
// used to change the orientation of the MK3MAG vertical to the horizontal plane
invert_blinking = 0;
break;
 
case 4:
// find Min and Max of the Z-Sensor
if(UncalMagZ < Zmin) Zmin = UncalMagZ;
if(UncalMagZ > Zmax) Zmax = UncalMagZ;
invert_blinking = 1;
break;
 
case 5:
// Save values
if(cal != calold) // avoid continously writing of eeprom!
{
Calibration.MagX.Range = Xmax - Xmin;
Calibration.MagX.Offset = (Xmin + Xmax) / 2;
Calibration.MagY.Range = Ymax - Ymin;
Calibration.MagY.Offset = (Ymin + Ymax) / 2;
Calibration.MagZ.Range = Zmax - Zmin;
Calibration.MagZ.Offset = (Zmin + Zmax) / 2;
if((Calibration.MagX.Range > 150) && (Calibration.MagY.Range > 150) && (Calibration.MagZ.Range > 150))
{
Calibration.Version = CALIBRATION_VERSION;
// indicate write process by setting the led off for 2 seconds
LED_GRN_OFF;
eeprom_write_block(&Calibration, &eeCalibration, sizeof(Calibration));
Led_Timer = SetDelay(2000);
// reset blinkcode
blinkcount = 0;
}
}
invert_blinking = 0;
break;
 
default:
break;
}
calold = cal;
}
 
 
void SetDebugValues(void)
{
DebugOut.Analog[0] = MagX;
DebugOut.Analog[1] = MagY;
DebugOut.Analog[2] = MagZ;
DebugOut.Analog[3] = UncalMagX;
DebugOut.Analog[4] = UncalMagY;
DebugOut.Analog[5] = UncalMagZ;
switch(AttitudeSource)
{
case ATTITUDE_SOURCE_ACC:
DebugOut.Analog[6] = AccAttitudeNick;
DebugOut.Analog[7] = AccAttitudeRoll;
break;
 
case ATTITUDE_SOURCE_UART:
DebugOut.Analog[6] = ExternData.Attitude[NICK];
DebugOut.Analog[7] = ExternData.Attitude[ROLL];
break;
 
 
case ATTITUDE_SOURCE_I2C:
DebugOut.Analog[6] = I2C_WriteAttitude.Nick;
DebugOut.Analog[7] = I2C_WriteAttitude.Roll;
break;
}
DebugOut.Analog[8] = Calibration.MagX.Offset;
DebugOut.Analog[9] = Calibration.MagX.Range;
DebugOut.Analog[10] = Calibration.MagY.Offset;
DebugOut.Analog[11] = Calibration.MagY.Range;
DebugOut.Analog[12] = Calibration.MagZ.Offset;
DebugOut.Analog[13] = Calibration.MagZ.Range;
if(I2C_WriteCal.CalByte) DebugOut.Analog[14] = I2C_WriteCal.CalByte;
else DebugOut.Analog[14] = ExternData.CalState;
DebugOut.Analog[15] = Heading;
DebugOut.Analog[16] = ExternData.UserParam[0];
DebugOut.Analog[17] = ExternData.UserParam[1];
DebugOut.Analog[18] = AccX;
DebugOut.Analog[19] = AccY;
DebugOut.Analog[20] = AccZ;
DebugOut.Analog[21] = RawAccX;
DebugOut.Analog[22] = RawAccY;
DebugOut.Analog[23] = RawAccZ;
DebugOut.Analog[24] = Calibration.AccX.Offset;
DebugOut.Analog[25] = Calibration.AccY.Offset;
DebugOut.Analog[26] = Calibration.AccZ.Offset;
DebugOut.Analog[29] = AttitudeSource;
}
 
void AccMeasurement(void)
{
if(AccPresent)
{
RawAccX = (RawAccX + (int16_t)ADC_GetValue(ACC_X))/2;
RawAccY = (RawAccY + (int16_t)ADC_GetValue(ACC_Y))/2;
RawAccZ = (RawAccZ + (int16_t)ADC_GetValue(ACC_Z))/2;
}
else
{
RawAccX = 0;
RawAccY = 0;
RawAccZ = 0;
}
}
 
int main (void)
{
// reset input pullup
DDRC &=~((1<<DDC6));
PORTC |= (1<<PORTC6);
 
LED_Init();
TIMER0_Init();
USART0_Init();
ADC_Init();
I2C_Init();
 
sei(); // enable globale interrupts
 
if(AccPresent)
{
USART0_Print("ACC present\n");
}
 
LED_GRN_ON;
 
Led_Timer = SetDelay(200);
 
// read calibration info from eeprom
eeprom_read_block(&Calibration, &eeCalibration, sizeof(Calibration));
 
ExternData.CalState = 0;
I2C_WriteCal.CalByte = 0;
 
 
// main loop
while (1)
{
FLIP_LOW;
Delay_ms(2);
RawMagnet1a = ADC_GetValue(MAG_X);
RawMagnet2a = -ADC_GetValue(MAG_Y);
RawMagnet3a = ADC_GetValue(MAG_Z);
AccMeasurement();
Delay_ms(1);
 
FLIP_HIGH;
Delay_ms(2);
RawMagnet1b = ADC_GetValue(MAG_X);
RawMagnet2b = -ADC_GetValue(MAG_Y);
RawMagnet3b = ADC_GetValue(MAG_Z);
AccMeasurement();
Delay_ms(1);
 
CalcFields();
 
if(ExternData.CalState || I2C_WriteCal.CalByte) Calibrate();
else CalcHeading();
 
// check data from USART
USART0_ProcessRxData();
 
if(NC_Connected) NC_Connected--;
if(FC_Connected) FC_Connected--;
// fall back to attitude estimation from acc sensor if NC or FC does'nt send attittude data
if(!FC_Connected && ! NC_Connected)
{
AttitudeSource = ATTITUDE_SOURCE_ACC;
Orientation = ORIENTATION_FC;
}
 
if(PC_Connected)
{
USART0_EnableTXD();
USART0_TransmitTxData();
PC_Connected--;
}
else
{
USART0_DisableTXD();
}
} // while(1)
}
 
/tags/V0.21b/main.h
0,0 → 1,34
#ifndef _MAIN_H_
#define _MAIN_H_
 
 
#include <avr/eeprom.h>
#include <inttypes.h>
 
 
typedef enum
{
ATTITUDE_SOURCE_I2C,
ATTITUDE_SOURCE_UART,
ATTITUDE_SOURCE_ACC
} AttitudeSource_t;
 
 
typedef enum
{
ORIENTATION_NC = 0,
ORIENTATION_FC = 1
} Orientation_t;
 
 
extern int16_t Heading;
 
extern AttitudeSource_t AttitudeSource;
extern Orientation_t Orientation;
 
extern int16_t MagX, MagY, MagZ;
 
void SetDebugValues(void);
 
#endif //_MAIN_H_
 
/tags/V0.21b/makefile
0,0 → 1,420
#--------------------------------------------------------------------
# MCU name
MCU = atmega168
F_CPU = 8000000
#-------------------------------------------------------------------
BOARD = 10
#BOARD = 11
VERSION_MAJOR = 0
VERSION_MINOR = 21
VERSION_PATCH = 1
 
VERSION_SERIAL_MAJOR = 10 # Serial Protocol Major Version
VERSION_SERIAL_MINOR = 0 # Serial Protocol Minor Version
NC_I2C_COMPATIBLE = 2 # I2C Protocol Version
#-------------------------------------------------------------------
 
# get SVN revision
REV := $(shell sh -c "cat .svn/entries | sed -n '4p'")
 
# Output format. (can be srec, ihex, binary)
FORMAT = ihex
 
# Target file name (without extension).
 
ifeq ($(VERSION_PATCH), 0)
TARGET = MK3Mag_MEGA168_V$(VERSION_MAJOR)_$(VERSION_MINOR)a_SVN$(REV)
endif
ifeq ($(VERSION_PATCH), 1)
TARGET = MK3Mag_MEGA168_V$(VERSION_MAJOR)_$(VERSION_MINOR)b_SVN$(REV)
endif
ifeq ($(VERSION_PATCH), 2)
TARGET = MK3Mag_MEGA168_V$(VERSION_MAJOR)_$(VERSION_MINOR)c_SVN$(REV)
endif
ifeq ($(VERSION_PATCH), 3)
TARGET = MK3Mag_MEGA168_V$(VERSION_MAJOR)_$(VERSION_MINOR)d_SVN$(REV)
endif
ifeq ($(VERSION_PATCH), 4)
TARGET = MK3Mag_MEGA168_V$(VERSION_MAJOR)_$(VERSION_MINOR)e_SVN$(REV)
endif
ifeq ($(VERSION_PATCH), 5)
TARGET = MK3Mag_MEGA168_V$(VERSION_MAJOR)_$(VERSION_MINOR)f_SVN$(REV)
endif
ifeq ($(VERSION_PATCH), 6)
TARGET = MK3Mag_MEGA168_V$(VERSION_MAJOR)_$(VERSION_MINOR)g_SVN$(REV)
endif
ifeq ($(VERSION_PATCH), 7)
TARGET = MK3Mag_MEGA168_V$(VERSION_MAJOR)_$(VERSION_MINOR)h_SVN$(REV)
endif
ifeq ($(VERSION_PATCH), 8)
TARGET = MK3Mag_MEGA168_V$(VERSION_MAJOR)_$(VERSION_MINOR)i_SVN$(REV)
endif
ifeq ($(VERSION_PATCH), 9)
TARGET = MK3Mag_MEGA168_V$(VERSION_MAJOR)_$(VERSION_MINOR)j_SVN$(REV)
endif
 
 
# Optimization level, can be [0, 1, 2, 3, s]. 0 turns off optimization.
# (Note: 3 is not always the best optimization level. See avr-libc FAQ.)
OPT = s
 
##########################################################################################################
# List C source files here. (C dependencies are automatically generated.)
SRC = main.c uart.c timer0.c analog.c twislave.c led.c
##########################################################################################################
 
 
# 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 =
 
 
# List any extra directories to look for include files here.
# Each directory must be seperated by a space.
EXTRAINCDIRS =
 
 
CDEFS = -DF_CPU=$(F_CPU)UL
 
# Optional compiler flags.
# -g: generate debugging information (for GDB, or for COFF conversion)
# -O*: optimization level
# -f...: tuning, see gcc manual and avr-libc documentation
# -Wall...: warning level
# -Wa,...: tell GCC to pass this to the assembler.
# -ahlms: create assembler listing
CFLAGS = -g -O$(OPT) \
-funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums \
-Wall -Wstrict-prototypes \
-Wa,-adhlns=$(<:.c=.lst) \
$(patsubst %,-I%,$(EXTRAINCDIRS))
 
 
# Set a "language standard" compiler flag.
# Unremark just one line below to set the language standard to use.
# gnu99 = C99 + GNU extensions. See GCC manual for more information.
#CFLAGS += -std=c89
#CFLAGS += -std=gnu89
#CFLAGS += -std=c99
CFLAGS += -std=gnu99
CFLAGS += $(CDEFS)
CFLAGS += -DVERSION_MAJOR=$(VERSION_MAJOR) -DVERSION_MINOR=$(VERSION_MINOR) -DVERSION_PATCH=$(VERSION_PATCH) -DVERSION_SERIAL_MAJOR=$(VERSION_SERIAL_MAJOR) -DVERSION_SERIAL_MINOR=$(VERSION_SERIAL_MINOR) -DBOARD=$(BOARD) -DNC_I2C_COMPATIBLE=$(NC_I2C_COMPATIBLE)
 
ifeq ($(AVR_CTRL_PLATINE), 1)
CFLAGS += -DAVR_CTRL_PLATINE=$(AVR_CTRL_PLATINE)
endif
 
 
 
# Optional assembler flags.
# -Wa,...: tell GCC to pass this to the assembler.
# -ahlms: 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]
ASFLAGS = -Wa,-adhlns=$(<:.S=.lst),-gstabs
 
 
 
# Optional linker flags.
# -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
 
 
 
# Additional libraries
 
# Minimalistic printf version
#LDFLAGS += -Wl,-u,vfprintf -lprintf_min
 
# Floating point printf version (requires -lm below)
#LDFLAGS += -Wl,-u,vfprintf -lprintf_flt
 
# -lm = math library
LDFLAGS += -lm
 
 
 
 
# Programming support using avrdude. Settings and variables.
 
# Programming hardware: alf avr910 avrisp bascom bsd
# dt006 pavr picoweb pony-stk200 sp12 stk200 stk500
#
# Type: avrdude -c ?
# to get a full listing.
#
 
AVRDUDE_PROGRAMMER = dt006
#AVRDUDE_PROGRAMMER = stk200
 
#AVRDUDE_PORT = com1 # programmer connected to serial device
AVRDUDE_PORT = lpt1 # programmer connected to parallel port
 
AVRDUDE_WRITE_FLASH = -U flash:w:$(TARGET).hex
#AVRDUDE_WRITE_EEPROM = -U eeprom:w:$(TARGET).eep
 
AVRDUDE_FLAGS = -F -p $(MCU) -P $(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER)
 
# 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 += -y
 
# Uncomment the following if you do /not/ wish a verification to be
# performed after programming the device.
#AVRDUDE_FLAGS += -V -E noreset
 
 
# Increase verbosity level. Please use this when submitting bug
# reports about avrdude. See <http://savannah.nongnu.org/projects/avrdude>
# to submit bug reports.
#AVRDUDE_FLAGS += -v -v
 
 
 
 
# ---------------------------------------------------------------------------
 
# Define directories, if needed.
DIRAVR = c:/winavr
DIRAVRBIN = $(DIRAVR)/bin
DIRAVRUTILS = $(DIRAVR)/utils/bin
DIRINC = .
DIRLIB = $(DIRAVR)/avr/lib
 
 
# Define programs and commands.
SHELL = sh
 
CC = avr-gcc
 
OBJCOPY = avr-objcopy
OBJDUMP = avr-objdump
SIZE = avr-size
 
 
# Programming support using avrdude.
AVRDUDE = avrdude
 
 
REMOVE = rm -f
COPY = cp
 
HEXSIZE = $(SIZE) --target=$(FORMAT) $(TARGET).hex
ELFSIZE = $(SIZE) -A $(TARGET).elf
 
 
 
# 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:
MSG_ASSEMBLING = Assembling:
MSG_CLEANING = Cleaning project:
 
 
 
 
# Define all object files.
OBJ = $(SRC:.c=.o) $(ASRC:.S=.o)
 
# Define all listing files.
LST = $(ASRC:.S=.lst) $(SRC:.c=.lst)
 
# Combine all necessary flags and optional flags.
# Add target processor to flags.
ALL_CFLAGS = -mmcu=$(MCU) -I. $(CFLAGS)
ALL_ASFLAGS = -mmcu=$(MCU) -I. -x assembler-with-cpp $(ASFLAGS)
 
 
 
# Default target.
all: begin gccversion sizebefore $(TARGET).elf $(TARGET).hex $(TARGET).eep \
$(TARGET).lss $(TARGET).sym sizeafter finished end
 
 
# 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)
 
finished:
@echo $(MSG_ERRORS_NONE)
 
end:
@echo $(MSG_END)
@echo
 
 
# Display size of file.
sizebefore:
@if [ -f $(TARGET).elf ]; then echo; echo $(MSG_SIZE_BEFORE); $(ELFSIZE); echo; fi
 
sizeafter:
@if [ -f $(TARGET).elf ]; then echo; echo $(MSG_SIZE_AFTER); $(ELFSIZE); echo; fi
 
 
 
# Display compiler version information.
gccversion :
@$(CC) --version
 
 
 
 
# Convert ELF to COFF for use in debugging / simulating in
# AVR Studio or VMLAB.
COFFCONVERT=$(OBJCOPY) --debugging \
--change-section-address .data-0x800000 \
--change-section-address .bss-0x800000 \
--change-section-address .noinit-0x800000 \
--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
 
 
 
 
# Program the device.
program: $(TARGET).hex $(TARGET).eep
$(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH) $(AVRDUDE_WRITE_EEPROM)
 
 
 
 
# Create final output files (.hex, .eep) from ELF output file.
%.hex: %.elf
@echo
@echo $(MSG_FLASH) $@
$(OBJCOPY) -O $(FORMAT) -R .eeprom $< $@
 
%.eep: %.elf
@echo
@echo $(MSG_EEPROM) $@
-$(OBJCOPY) -j .eeprom --set-section-flags=.eeprom="alloc,load" \
--change-section-lma .eeprom=0 -O $(FORMAT) $< $@
 
# Create extended listing file from ELF output file.
%.lss: %.elf
@echo
@echo $(MSG_EXTENDED_LISTING) $@
$(OBJDUMP) -h -S $< > $@
 
# Create a symbol table from ELF output file.
%.sym: %.elf
@echo
@echo $(MSG_SYMBOL_TABLE) $@
avr-nm -n $< > $@
 
 
 
# Link: create ELF output file from object files.
.SECONDARY : $(TARGET).elf
.PRECIOUS : $(OBJ)
%.elf: $(OBJ)
@echo
@echo $(MSG_LINKING) $@
$(CC) $(ALL_CFLAGS) $(OBJ) --output $@ $(LDFLAGS)
 
 
# Compile: create object files from C source files.
%.o : %.c
@echo
@echo $(MSG_COMPILING) $<
$(CC) -c $(ALL_CFLAGS) $< -o $@
 
 
# Compile: create assembler files from C source files.
%.s : %.c
$(CC) -S $(ALL_CFLAGS) $< -o $@
 
 
# Assemble: create object files from assembler source files.
%.o : %.S
@echo
@echo $(MSG_ASSEMBLING) $<
$(CC) -c $(ALL_ASFLAGS) $< -o $@
 
 
 
 
 
 
# Target: clean project.
clean: begin clean_list finished end
 
clean_list :
@echo
@echo $(MSG_CLEANING)
# $(REMOVE) $(TARGET).hex
# $(REMOVE) $(TARGET).eep
# $(REMOVE) $(TARGET).obj
$(REMOVE) $(TARGET).cof
$(REMOVE) $(TARGET).elf
$(REMOVE) $(TARGET).map
$(REMOVE) $(TARGET).obj
$(REMOVE) $(TARGET).a90
$(REMOVE) $(TARGET).sym
$(REMOVE) $(TARGET).lnk
$(REMOVE) $(TARGET).lss
$(REMOVE) $(OBJ)
$(REMOVE) $(LST)
$(REMOVE) $(SRC:.c=.s)
$(REMOVE) $(SRC:.c=.d)
 
 
# Automatically generate C source code dependencies.
# (Code originally taken from the GNU make user manual and modified
# (See README.txt Credits).)
#
# Note that this will work with sh (bash) and sed that is shipped with WinAVR
# (see the SHELL variable defined above).
# This may not work with other shells or other seds.
#
%.d: %.c
set -e; $(CC) -MM $(ALL_CFLAGS) $< \
| sed 's,\(.*\)\.o[ :]*,\1.o \1.d : ,g' > $@; \
[ -s $@ ] || rm -f $@
 
 
# Remove the '-' if you want to see the dependency files generated.
-include $(SRC:.c=.d)
 
 
 
# Listing of phony targets.
.PHONY : all begin finish end sizebefore sizeafter gccversion coff extcoff \
clean clean_list program
 
/tags/V0.21b/timer0.c
0,0 → 1,167
/*#######################################################################################
MK3Mag 3D-Magnet sensor
!!! THIS IS NOT FREE SOFTWARE !!!
#######################################################################################*/
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Copyright (c) 05.2008 Holger Buss
// + Thanks to Ilja Fähnrich (P_Latzhalter)
// + Nur für den privaten Gebrauch
// + www.MikroKopter.com
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Die Portierung der Software (oder Teile davon) auf andere Systeme (ausser der Hardware von www.mikrokopter.de) ist nur
// + mit unserer Zustimmung zulässig
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Es gilt für das gesamte Projekt (Hardware, Software, Binärfiles, Sourcecode und Dokumentation),
// + dass eine Nutzung (auch auszugsweise) nur für den privaten (nicht-kommerziellen) Gebrauch zulässig ist.
// + AUSNAHME: Ein bei www.mikrokopter.de erworbener vorbestückter MK3Mag darf als Baugruppe auch in kommerziellen Systemen verbaut werden
// + Im Zweifelsfall bitte anfragen bei: info@mikrokopter.de
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Werden Teile des Quellcodes (mit oder ohne Modifikation) weiterverwendet oder veröffentlicht,
// + unterliegen sie auch diesen Nutzungsbedingungen und diese Nutzungsbedingungen incl. Copyright müssen dann beiliegen
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Sollte die Software (auch auszugesweise) oder sonstige Informationen des MikroKopter-Projekts
// + auf anderen Webseiten oder sonstigen Medien veröffentlicht werden, muss unsere Webseite "http://www.mikrokopter.de"
// + eindeutig als Ursprung verlinkt werden
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Keine Gewähr auf Fehlerfreiheit, Vollständigkeit oder Funktion
// + Benutzung auf eigene Gefahr
// + Wir übernehmen keinerlei Haftung für direkte oder indirekte Personen- oder Sachschäden
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Die Funktion printf_P() unterliegt ihrer eigenen Lizenz und ist hiervon nicht betroffen
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Redistributions of source code (with or without modifications) must retain the above copyright notice,
// + this list of conditions and the following disclaimer.
// + * PORTING this software (or parts of it) to systems (other than hardware from www.mikrokopter.de) is NOT allowed
// + * Neither the name of the copyright holders nor the names of contributors may be used to endorse or promote products derived
// + from this software without specific prior written permission.
// + * The use of this project (hardware, software, binary files, sources and documentation) is only permittet
// + for non-commercial use (directly or indirectly)
// + Commercial use (for excample: selling of MikroKopters, selling of PCBs, assembly, ...) is only permitted
// + with our written permission
// + Exception: A preassembled MK3Mag, purchased from www.mikrokopter.de may be used as a part of commercial systems
// + In case of doubt please contact: info@MikroKopter.de
// + * If sources or documentations are redistributet on other webpages, our webpage (http://www.MikroKopter.de) must be
// + clearly linked as origin
// + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// + POSSIBILITY OF SUCH DAMAGE.
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#include <inttypes.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include "main.h"
 
volatile uint16_t CountMilliseconds = 0;
volatile uint16_t I2C_Timeout = 0;
 
 
/*****************************************************/
/* Initialize Timer 0 */
/*****************************************************/
void TIMER0_Init(void)
{
// set PB2 as output for the PWM used to signal compass heading
DDRB |= (1<<DDB2);
PORTB &= ~(1<<PORTB2);
 
 
// Timer/Counter 0 Control Register A
 
// Normal Timer Counter Mode (Bits WGM02 = 0, WGM01 = 0, WGM00 = 0)
// OC0A disconnected (Bits COM0A1 = 0, COM0A0 = 0)
// OC0B disconnected (Bits COM0B1 = 0, COM0B0 = 0)
TCCR0A &= ~((1<<COM0A1)|(1<<COM0A0)|(1<<COM0B1)|(1<<COM0B0)|(1<<WGM01)|(1<<WGM00));
 
// Timer/Counter 0 Control Register B
 
// set clock devider for timer 0 to SYSKLOCK/8 = 8MHz / 8 = 1MHz
// i.e. the timer increments from 0x00 to 0xFF with an update rate of 2.5 MHz
// hence the timer overflow interrupt frequency is 2.5 MHz / 256 = 9.765 kHz
 
// divider 8 (Bits CS02 = 0, CS01 = 1, CS00 = 0)
TCCR0B &= ~((1<<FOC0A)|(1<<FOC0B)|(1<<WGM02)|(1<<CS02));
TCCR0B = (1<<CS01)|(0<<CS00);
 
// init Timer/Counter 0 Register
TCNT0 = 0;
 
// Timer/Counter 0 Interrupt Mask Register
// enable timer overflow interrupt only
TIMSK0 &= ~((1<<OCIE0B)|(1<<OCIE0A));
TIMSK0 |= (1<<TOIE0);
 
}
 
 
// -----------------------------------------------------------------------
ISR(TIMER0_OVF_vect)
{
static uint8_t cnt;
static uint16_t cmps_cnt;
 
// reload timer register so that overflow occurs after 100 increments at 1 MHz
// resulting in a calling rate of this ISR of 10kHz or 0.1 ms.
TCNT0 -= 101;
 
// disable PWM when bad compass heading value
if(Heading < 0)
{
PORTB &= ~(1<<PORTB2);
cmps_cnt = 0;
}
else
{
// if a periode of 38.0 ms is over
if(++cmps_cnt >= 380)
{
// set PWM out to high
PORTB |= (1<<PORTB2);
// reset periode counter
cmps_cnt = 0;
}
// if the delay in 0.1 ms is equal to Heading + 10
else if(cmps_cnt >= (Heading + 10))
{
// set PWM out to low
PORTB &= ~(1<<PORTB2);
}
}
 
if(!--cnt)
{
// every 10th run (1kHz or 1ms)
cnt = 10;
CountMilliseconds++;
if(I2C_Timeout) I2C_Timeout--;
}
}
 
 
// -----------------------------------------------------------------------
uint16_t SetDelay (uint16_t t)
{
return(CountMilliseconds + t - 1);
}
 
// -----------------------------------------------------------------------
int8_t CheckDelay(uint16_t t)
{
return(((t - CountMilliseconds) & 0x8000) >> 8); // check sign bit
}
 
// -----------------------------------------------------------------------
void Delay_ms(uint16_t wait)
{
uint16_t t_stop;
t_stop = SetDelay(wait);
while (!CheckDelay(t_stop));
}
 
/tags/V0.21b/timer0.h
0,0 → 1,17
#ifndef _TIMER0_H
#define _TIMER0_H
 
#include <inttypes.h>
 
extern volatile uint16_t CountMilliseconds;
extern volatile uint16_t I2C_Timeout;
 
 
void TIMER0_Init(void);
uint16_t SetDelay (uint16_t t);
int8_t CheckDelay(uint16_t t);
void Delay_ms(uint16_t wait);
 
 
#endif //_TIMER0_H
 
/tags/V0.21b/twislave.c
0,0 → 1,291
/*#######################################################################################
MK3Mag 3D-Magnet sensor
!!! THIS IS NOT FREE SOFTWARE !!!
#######################################################################################*/
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Copyright (c) 05.2008 Holger Buss
// + Thanks to Ilja Fähnrich (P_Latzhalter)
// + Nur für den privaten Gebrauch
// + www.MikroKopter.com
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Die Portierung der Software (oder Teile davon) auf andere Systeme (ausser der Hardware von www.mikrokopter.de) ist nur
// + mit unserer Zustimmung zulässig
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Es gilt für das gesamte Projekt (Hardware, Software, Binärfiles, Sourcecode und Dokumentation),
// + dass eine Nutzung (auch auszugsweise) nur für den privaten (nicht-kommerziellen) Gebrauch zulässig ist.
// + AUSNAHME: Ein bei www.mikrokopter.de erworbener vorbestückter MK3Mag darf als Baugruppe auch in kommerziellen Systemen verbaut werden
// + Im Zweifelsfall bitte anfragen bei: info@mikrokopter.de
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Werden Teile des Quellcodes (mit oder ohne Modifikation) weiterverwendet oder veröffentlicht,
// + unterliegen sie auch diesen Nutzungsbedingungen und diese Nutzungsbedingungen incl. Copyright müssen dann beiliegen
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Sollte die Software (auch auszugesweise) oder sonstige Informationen des MikroKopter-Projekts
// + auf anderen Webseiten oder sonstigen Medien veröffentlicht werden, muss unsere Webseite "http://www.mikrokopter.de"
// + eindeutig als Ursprung verlinkt werden
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Keine Gewähr auf Fehlerfreiheit, Vollständigkeit oder Funktion
// + Benutzung auf eigene Gefahr
// + Wir übernehmen keinerlei Haftung für direkte oder indirekte Personen- oder Sachschäden
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Die Funktion printf_P() unterliegt ihrer eigenen Lizenz und ist hiervon nicht betroffen
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Redistributions of source code (with or without modifications) must retain the above copyright notice,
// + this list of conditions and the following disclaimer.
// + * PORTING this software (or parts of it) to systems (other than hardware from www.mikrokopter.de) is NOT allowed
// + * Neither the name of the copyright holders nor the names of contributors may be used to endorse or promote products derived
// + from this software without specific prior written permission.
// + * The use of this project (hardware, software, binary files, sources and documentation) is only permittet
// + for non-commercial use (directly or indirectly)
// + Commercial use (for excample: selling of MikroKopters, selling of PCBs, assembly, ...) is only permitted
// + with our written permission
// + Exception: A preassembled MK3Mag, purchased from www.mikrokopter.de may be used as a part of commercial systems
// + In case of doubt please contact: info@MikroKopter.de
// + * If sources or documentations are redistributet on other webpages, our webpage (http://www.MikroKopter.de) must be
// + clearly linked as origin
// + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// + POSSIBILITY OF SUCH DAMAGE.
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/twi.h>
#include "twislave.h"
#include "uart.h"
#include "main.h"
#include "timer0.h"
#include "led.h"
 
 
volatile uint8_t I2C_RxBufferSize = 0, I2C_TxBufferSize = 0;
volatile uint8_t *I2C_TxBuffer = 0, *I2C_RxBuffer = 0;
volatile uint8_t Tx_Idx = 0, Rx_Idx = 0;
 
volatile uint8_t I2C_PrimRxBuffer[10];
 
uint8_t NC_Connected = 0;
I2C_Heading_t I2C_Heading;
I2C_WriteAttitude_t I2C_WriteAttitude;
I2C_Mag_t I2C_Mag;
I2C_Version_t I2C_Version;
I2C_WriteCal_t I2C_WriteCal;
 
 
void I2C_Init(void)
{
 
uint8_t sreg;
 
// backup status register
sreg = SREG;
// disable global interrupts
cli();
 
// SCK/SCL and MISO/SDA are at put together on the same connector pin in the schematic
 
// set PB4 (SCK) and PB5 (MISO) as input pull up
DDRB &= ~((1<<DDB4)|(1<<DDB5));
PORTB |= ((1<<PORTB4)|(1<<PORTB5));
 
// set PC4 (SDA) and PC5 (SCL) as input tristate
DDRC &= ~((1<<DDC4)|(1<<DDC5));
PORTC &= ~((1<<PORTC4)|(1<<PORTC5));
 
I2C_TxBuffer = 0;
Tx_Idx = 0;
I2C_TxBufferSize = 0;
I2C_RxBuffer = 0;
Rx_Idx = 0;
I2C_RxBufferSize = 0;
 
 
 
TWCR &= ~(1<<TWSTA)|(1<<TWSTO);
TWCR|= (1<<TWEA) | (1<<TWEN)|(1<<TWIE);
 
// set own address
// set own address in the upper 7 bits
TWAR = I2C_SLAVE_ADDRESS; // set own address only the upper 7 bits are relevant
// TWI Control Register
// enable TWI Acknowledge Bit (TWEA = 1)
// disable TWI START Condition Bit (TWSTA = 0), SLAVE
// disable TWI STOP Condition Bit (TWSTO = 0), SLAVE
// enable TWI (TWEN = 1)
// enable TWI Interrupt (TWIE = 1)
TWCR |= (1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(1<<TWEA)|(0<<TWSTA)|(1<<TWSTO)|(0<<TWWC);
// update version info
I2C_Version.Major = VERSION_MAJOR;
I2C_Version.Minor = VERSION_MINOR;
I2C_Version.Patch = VERSION_PATCH;
I2C_Version.Compatible = NC_I2C_COMPATIBLE;
 
// resore status register
SREG = sreg;
}
 
// send ACK after recieving a byte / ACK is expected after transmitting a byte
#define TWCR_ACK TWCR = (1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(1<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|(0<<TWWC)
// send no ACK after recieving a byte / No ACK is expected after transmitting a byte
#define TWCR_NACK TWCR = (1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(0<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|(0<<TWWC)
// switched to the non adressed slave mode
#define TWCR_RESET TWCR = (1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(1<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|(0<<TWWC)
// The bit pattern for TWCR_ACK and TWCR_RESET are equal. This is no errro but used for better understanding.
#define TWCR_CLEARBUS TWCR = (1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(1<<TWEA)|(0<<TWSTA)|(1<<TWSTO)|(0<<TWWC)
 
ISR (TWI_vect)
{
uint8_t data;
static uint8_t crc;
// check event
switch (TW_STATUS)
{
case TW_SR_SLA_ACK: // slave addressed in receiver mode and ack has been returned
Rx_Idx = 0xFF; // reset rx buffer pointer
TWCR_ACK; // trigger receiving of first data byte and send ack afterwards
return;
 
case TW_SR_DATA_ACK: // data has been received and ack has been returned
data = TWDR;
if (Rx_Idx == 0xFF)
{ // if the first byte after slave addressing was received
switch(data)
{
case I2C_CMD_VERSION:
I2C_TxBuffer = (uint8_t *)&I2C_Version;
I2C_TxBufferSize = sizeof(I2C_Version);
I2C_RxBuffer = 0;
I2C_RxBufferSize = 0;
break;
 
case I2C_CMD_WRITE_CAL:
I2C_TxBuffer = (uint8_t *)&I2C_WriteCal;
I2C_TxBufferSize = sizeof(I2C_WriteCal);
I2C_RxBuffer = (uint8_t *)&I2C_WriteCal;
I2C_RxBufferSize = sizeof(I2C_WriteCal);
break;
 
case I2C_CMD_READ_MAG:
I2C_TxBuffer = (uint8_t *)&I2C_Mag;
I2C_TxBufferSize = sizeof(I2C_Mag);
I2C_RxBuffer = 0;
I2C_RxBufferSize = 0;
 
I2C_Mag.MagX = MagX;
I2C_Mag.MagY = MagY;
I2C_Mag.MagZ = MagZ;
break;
 
case I2C_CMD_READ_HEADING:
I2C_TxBuffer = (uint8_t *)&I2C_Heading;
I2C_TxBufferSize = sizeof(I2C_Heading);
I2C_RxBuffer = (uint8_t *)&I2C_WriteAttitude;
I2C_RxBufferSize = sizeof(I2C_WriteAttitude);
I2C_Heading.Heading = Heading;
AttitudeSource = ATTITUDE_SOURCE_I2C;
Orientation = ORIENTATION_NC;
NC_Connected = 255;
break;
default: // unknown command id
I2C_RxBuffer = 0;
I2C_RxBufferSize = 0;
I2C_TxBuffer = 0;
I2C_TxBufferSize = 0;
break;
}
Rx_Idx = 0; // set rx buffer index to start of the buffer
crc = data;
}
else // Rx_Idx != 0xFF
{
// fill receiver buffer with the byte that has been received
// if buffer exist and there is still some free space
if(Rx_Idx < I2C_RxBufferSize)
{
I2C_PrimRxBuffer[Rx_Idx] = data;
crc += data;
}
else if (Rx_Idx == I2C_RxBufferSize) // crc byte was transfered
{ // if checksum matched
if(crc == data)
{ // and RxBuffer exist
if(I2C_RxBuffer != 0)
{ // copy data to rx buffer
for(data = 0; data < I2C_RxBufferSize; data++)
{
I2C_RxBuffer[data] = I2C_PrimRxBuffer[data];
}
}
DebugOut.Analog[31]++;
}
else
{
DebugOut.Analog[30]++;
}
}
// else ignore data
Rx_Idx++;
}
TWCR_ACK;
return;
 
case TW_ST_SLA_ACK: // slave transmitter selected
// reset index to start of tx buffer
Tx_Idx = 0;
crc = 0;
// if tx buffer exist and there is at least one byte to transfer
if((I2C_TxBuffer != 0) && (I2C_TxBufferSize > 1))
{
data = I2C_TxBuffer[Tx_Idx];
 
}
else
{ // send 0x00 if no tx buffer exist or all bytes of the tx buffer have been transmitted
data = 0x00;
}
crc += data;
Tx_Idx++;
TWDR = data;
TWCR_ACK;
return;
 
case TW_ST_DATA_ACK: // data byte has been transmitted ack has been received
// put next byte from tx buffer to the data register
if((I2C_TxBuffer != 0) && (Tx_Idx < I2C_TxBufferSize))
{
data = I2C_TxBuffer[Tx_Idx];
crc += data;
}
else if (Tx_Idx == I2C_TxBufferSize)
{ // send crc byte at the end
data = crc;
}
else
{
data = 0x00;
}
Tx_Idx++;
TWDR = data;
TWCR_ACK;
return;
 
case TW_BUS_ERROR: // Bus-Error
TWCR_CLEARBUS; // free bus, reset to nonselected slave
return;
 
case TW_ST_DATA_NACK: // data transmitted, NACK received
case TW_ST_LAST_DATA: // last data byte transmitted, ACK received
case TW_SR_STOP: // stop or repeated start condition received while selected
default:
TWCR_RESET; // switch to the not addressed slave mode, own SLA will be recognized
return;
}
}
 
 
/tags/V0.21b/twislave.h
0,0 → 1,63
#ifndef _TWI_SLAVE_H_
#define _TWI_SLAVE_H_
 
#include <inttypes.h>
 
#define I2C_SLAVE_ADDRESS 0x50
 
#define I2C_CMD_VERSION 0x01
#define I2C_CMD_READ_MAG 0x02
#define I2C_CMD_READ_HEADING 0x03
#define I2C_CMD_WRITE_CAL 0x04
#define I2C_CMD_WRITE_EEPROM 0x0A
#define I2C_CMD_READ_EEPROM 0x0B
 
 
typedef struct
{
uint8_t Major;
uint8_t Minor;
uint8_t Patch;
uint8_t Compatible;
} I2C_Version_t;
 
typedef struct
{
int16_t MagX;
int16_t MagY;
int16_t MagZ;
} I2C_Mag_t;
 
 
typedef struct
{
int16_t Nick;
int16_t Roll;
} I2C_WriteAttitude_t;
 
 
typedef struct
{
uint8_t CalByte;
uint8_t Dummy1;
uint8_t Dummy2;
} I2C_WriteCal_t;
 
typedef struct
{
int16_t Heading;
} I2C_Heading_t;
 
extern uint8_t NC_Connected;
extern I2C_Heading_t I2C_Heading;
extern I2C_WriteAttitude_t I2C_WriteAttitude;
extern I2C_Mag_t I2C_Mag;
extern I2C_Version_t I2C_Version;
extern I2C_WriteCal_t I2C_WriteCal;
 
 
void I2C_Init(void);
 
 
#endif // _TWI_SLAVE_H_
 
/tags/V0.21b/uart.c
0,0 → 1,639
/*#######################################################################################
MK3Mag 3D-Magnet sensor
!!! THIS IS NOT FREE SOFTWARE !!!
#######################################################################################*/
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Copyright (c) 05.2008 Holger Buss
// + Thanks to Ilja Fähnrich (P_Latzhalter)
// + Nur für den privaten Gebrauch
// + www.MikroKopter.com
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Die Portierung der Software (oder Teile davon) auf andere Systeme (ausser der Hardware von www.mikrokopter.de) ist nur
// + mit unserer Zustimmung zulässig
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Es gilt für das gesamte Projekt (Hardware, Software, Binärfiles, Sourcecode und Dokumentation),
// + dass eine Nutzung (auch auszugsweise) nur für den privaten (nicht-kommerziellen) Gebrauch zulässig ist.
// + AUSNAHME: Ein bei www.mikrokopter.de erworbener vorbestückter MK3Mag darf als Baugruppe auch in kommerziellen Systemen verbaut werden
// + Im Zweifelsfall bitte anfragen bei: info@mikrokopter.de
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Werden Teile des Quellcodes (mit oder ohne Modifikation) weiterverwendet oder veröffentlicht,
// + unterliegen sie auch diesen Nutzungsbedingungen und diese Nutzungsbedingungen incl. Copyright müssen dann beiliegen
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Sollte die Software (auch auszugesweise) oder sonstige Informationen des MikroKopter-Projekts
// + auf anderen Webseiten oder sonstigen Medien veröffentlicht werden, muss unsere Webseite "http://www.mikrokopter.de"
// + eindeutig als Ursprung verlinkt werden
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Keine Gewähr auf Fehlerfreiheit, Vollständigkeit oder Funktion
// + Benutzung auf eigene Gefahr
// + Wir übernehmen keinerlei Haftung für direkte oder indirekte Personen- oder Sachschäden
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Die Funktion printf_P() unterliegt ihrer eigenen Lizenz und ist hiervon nicht betroffen
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Redistributions of source code (with or without modifications) must retain the above copyright notice,
// + this list of conditions and the following disclaimer.
// + * PORTING this software (or parts of it) to systems (other than hardware from www.mikrokopter.de) is NOT allowed
// + * Neither the name of the copyright holders nor the names of contributors may be used to endorse or promote products derived
// + from this software without specific prior written permission.
// + * The use of this project (hardware, software, binary files, sources and documentation) is only permittet
// + for non-commercial use (directly or indirectly)
// + Commercial use (for excample: selling of MikroKopters, selling of PCBs, assembly, ...) is only permitted
// + with our written permission
// + Exception: A preassembled MK3Mag, purchased from www.mikrokopter.de may be used as a part of commercial systems
// + In case of doubt please contact: info@MikroKopter.de
// + * If sources or documentations are redistributet on other webpages, our webpage (http://www.MikroKopter.de) must be
// + clearly linked as origin
// + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// + POSSIBILITY OF SUCH DAMAGE.
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/wdt.h>
#include <stdarg.h>
#include <string.h>
#include "main.h"
#include "uart.h"
#include "timer0.h"
#include "twislave.h"
 
// slave addresses
#define FC_ADDRESS 1
#define NC_ADDRESS 2
#define MK3MAG_ADDRESS 3
 
#define FALSE 0
#define TRUE 1
 
// keep buffers as small as possible
#define TXD_BUFFER_LEN 100
#define RXD_BUFFER_LEN 30
 
volatile uint8_t txd_buffer[TXD_BUFFER_LEN];
volatile uint8_t rxd_buffer_locked = FALSE;
volatile uint8_t rxd_buffer[RXD_BUFFER_LEN];
volatile uint8_t txd_complete = TRUE;
volatile uint8_t ReceivedBytes = 0;
volatile uint8_t *pRxData = 0;
volatile uint8_t RxDataLen = 0;
 
// send flags
#define RQST_VERSION_INFO 0x01
#define RQST_DEBUG_DATA 0x02
#define RQST_DEBUG_LABEL 0x04
#define RQST_COMPASS_HEADING 0x08
#define RQST_EXTERN_CTRL 0x10
 
 
uint8_t RequestFlags = 0x00;
uint8_t RequestDebugLabel = 0;
uint8_t ConfirmFrame = 0;
 
uint8_t PC_Connected = 0;
uint8_t FC_Connected = 0;
 
 
DebugOut_t DebugOut;
ExternData_t ExternData;
ExternControl_t ExternControl;
UART_VersionInfo_t UART_VersionInfo;
 
uint16_t DebugData_Timer;
uint16_t DebugData_Interval = 500;
 
const uint8_t ANALOG_LABEL[32][16] =
{
//1234567890123456
"Magnet X ", //0
"Magnet Y ",
"Magnet Z ",
"RawMagnet X ",
"RawMagnet Y ",
"RawMagnet Z ", //5
"Attitude Nick ",
"Attitude Roll ",
"Magnet X Offset ",
"Magnet X Range ",
"Magnet Y Offset ", //10
"Magnet Y Range ",
"Magnet Z Offset ",
"Magnet Z Range ",
"Calstate ",
"Heading ", //15
"User0 ",
"User1 ",
"Acc X ",
"Acc Y ",
"Acc Z ", //20
"RawAcc X ",
"RawAcc Y ",
"RawAcc Z ",
"Acc X Offset ",
"Acc Y Offset ", //25
"Acc Z Offset ",
"Analog27 ",
"Analog28 ",
"Analog29 ",
"I2C Error ", //30
"I2C Okay "
};
 
 
/****************************************************************/
/* Initialization of the USART0 */
/****************************************************************/
void USART0_Init (void)
{
uint8_t sreg = SREG;
uint16_t ubrr = (uint16_t) ((uint32_t) F_CPU/(8 * BAUD_RATE) - 1);
 
// disable all interrupts before configuration
cli();
 
// disable RX-Interrupt
UCSR0B &= ~(1 << RXCIE0);
// disable TX-Interrupt
UCSR0B &= ~(1 << TXCIE0);
 
// set direction of RXD0 and TXD0 pins
 
// set RXD0 (PD0) as an input pin tristate
DDRD &= ~(1 << DDD0);
PORTD &= ~(1 << PORTD0);
// set TXD0 (PD1) as an output pin
DDRD |= (1 << DDD1);
PORTD &= ~(1 << PORTD1);
 
 
// USART0 Baud Rate Register
// set clock divider
UBRR0H = (uint8_t)(ubrr >> 8);
UBRR0L = (uint8_t)ubrr;
 
// USART0 Control and Status Register A, B, C
 
// enable double speed operation
UCSR0A |= (1 << U2X0);
 
// set asynchronous mode
UCSR0C &= ~(1 << UMSEL01);
UCSR0C &= ~(1 << UMSEL00);
// no parity
UCSR0C &= ~(1 << UPM01);
UCSR0C &= ~(1 << UPM00);
// 1 stop bit
UCSR0C &= ~(1 << USBS0);
// 8-bit
UCSR0B &= ~(1 << UCSZ02);
UCSR0C |= (1 << UCSZ01);
UCSR0C |= (1 << UCSZ00);
 
// enable receiver and transmitter
UCSR0B |= (1 << RXEN0);
UCSR0B |= (1 << TXEN0);
 
// flush receive buffer
while ( UCSR0A & (1<<RXC0) ) UDR0;
 
// enable RX-Interrupt
UCSR0B |= (1 << RXCIE0);
// enable TX-Interrupt
UCSR0B |= (1 << TXCIE0);
 
// initialize the debug timer
DebugData_Timer = SetDelay(DebugData_Interval);
 
// unlock rxd_buffer
rxd_buffer_locked = FALSE;
pRxData = 0;
RxDataLen = 0;
 
// no bytes to send
txd_complete = TRUE;
 
 
UART_VersionInfo.SWMajor = VERSION_MAJOR;
UART_VersionInfo.SWMinor = VERSION_MINOR;
UART_VersionInfo.SWPatch = VERSION_PATCH;
UART_VersionInfo.ProtoMajor = VERSION_SERIAL_MAJOR;
UART_VersionInfo.ProtoMinor = VERSION_SERIAL_MINOR;
 
// Version beim Start ausgeben (nicht schön, aber geht... )
USART0_putchar ('\n');
USART0_putchar ('C');
USART0_putchar ('P');
USART0_putchar (':');
USART0_putchar ('V');
USART0_putchar (0x30 + VERSION_MAJOR);
USART0_putchar ('.');
USART0_putchar (0x30 + VERSION_MINOR/10);
USART0_putchar (0x30 + VERSION_MINOR%10);
USART0_putchar ('a' + VERSION_PATCH);
USART0_putchar ('\n');
 
// restore global interrupt flags
SREG = sreg;
}
 
// ---------------------------------------------------------------------------------
void USART0_EnableTXD(void)
{
DDRD |= (1<<DDD1); // set TXD pin as output
PORTD &= ~(1 << PORTD1);
UCSR0B |= (1 << TXEN0); // enable TX in USART
UCSR0B |= (1 << TXCIE0); // disable TX-Interrupt
}
 
// ---------------------------------------------------------------------------------
void USART0_DisableTXD(void)
{
while(!txd_complete){ };
 
UCSR0B &= ~(1 << TXCIE0); // disable TX-Interrupt
UCSR0B &= ~(1 << TXEN0); // disable TXD in USART
DDRD &= ~(1<<DDD1); // set TXD pin as input
PORTD &= ~(1 << PORTD1);
}
 
/****************************************************************/
/* USART0 transmitter ISR */
/****************************************************************/
ISR(USART_TX_vect)
{
static uint16_t ptr_txd_buffer = 0;
uint8_t tmp_tx;
if(!txd_complete) // transmission not completed
{
ptr_txd_buffer++; // die [0] wurde schon gesendet
tmp_tx = txd_buffer[ptr_txd_buffer];
// if terminating character or end of txd buffer was reached
if((tmp_tx == '\r') || (ptr_txd_buffer == TXD_BUFFER_LEN))
{
ptr_txd_buffer = 0; // reset txd pointer
txd_complete = TRUE; // stop transmission
}
UDR0 = tmp_tx; // send current byte will trigger this ISR again
}
// transmission completed
else ptr_txd_buffer = 0;
}
 
/****************************************************************/
/* USART0 receiver ISR */
/****************************************************************/
ISR(USART_RX_vect)
{
static uint16_t crc;
uint8_t crc1, crc2;
uint8_t c;
static uint8_t ptr_rxd_buffer = 0;
 
c = UDR0; // catch the received byte
 
if(rxd_buffer_locked) return; // if rxd buffer is locked immediately return
 
// the rxd buffer is unlocked
if((ptr_rxd_buffer == 0) && (c == '#')) // if rxd buffer is empty and syncronisation character is received
{
rxd_buffer[ptr_rxd_buffer++] = c; // copy 1st byte to buffer
crc = c; // init crc
}
#if 0
else if (ptr_rxd_buffer == 1) // handle address
{
rxd_buffer[ptr_rxd_buffer++] = c; // copy byte to rxd buffer
crc += c; // update crc
}
#endif
else if (ptr_rxd_buffer < RXD_BUFFER_LEN) // collect incomming bytes
{
if(c != '\r') // no termination character
{
rxd_buffer[ptr_rxd_buffer++] = c; // copy byte to rxd buffer
crc += c; // update crc
}
else // termination character was received
{
// the last 2 bytes are no subject for checksum calculation
// they are the checksum itself
crc -= rxd_buffer[ptr_rxd_buffer-2];
crc -= rxd_buffer[ptr_rxd_buffer-1];
// calculate checksum from transmitted data
crc %= 4096;
crc1 = '=' + crc / 64;
crc2 = '=' + crc % 64;
// compare checksum to transmitted checksum bytes
if((crc1 == rxd_buffer[ptr_rxd_buffer-2]) && (crc2 == rxd_buffer[ptr_rxd_buffer-1]))
{ // checksum valid
rxd_buffer[ptr_rxd_buffer] = '\r'; // set termination character
ReceivedBytes = ptr_rxd_buffer + 1;// store number of received bytes
rxd_buffer_locked = TRUE; // lock the rxd buffer
// if 2nd byte is an 'R' enable watchdog that will result in an reset
if(rxd_buffer[2] == 'R') {wdt_enable(WDTO_250MS);} // Reset-Commando
}
else
{ // checksum invalid
rxd_buffer_locked = FALSE; // unlock rxd buffer
}
ptr_rxd_buffer = 0; // reset rxd buffer pointer
}
}
else // rxd buffer overrun
{
ptr_rxd_buffer = 0; // reset rxd buffer
rxd_buffer_locked = FALSE; // unlock rxd buffer
}
}
 
 
// --------------------------------------------------------------------------
void AddCRC(uint16_t datalen)
{
uint16_t tmpCRC = 0, i;
for(i = 0; i < datalen; i++)
{
tmpCRC += txd_buffer[i];
}
tmpCRC %= 4096;
txd_buffer[i++] = '=' + tmpCRC / 64;
txd_buffer[i++] = '=' + tmpCRC % 64;
txd_buffer[i++] = '\r';
txd_complete = FALSE;
UDR0 = txd_buffer[0]; // initiates the transmission (continued in the TXD ISR)
}
 
 
 
// --------------------------------------------------------------------------
void SendOutData(uint8_t cmd, uint8_t address, uint8_t numofbuffers, ...) // uint8_t *pdata, uint8_t len, ...
{
va_list ap;
uint16_t pt = 0;
uint8_t a,b,c;
uint8_t ptr = 0;
 
uint8_t *pdata = 0;
int len = 0;
 
txd_buffer[pt++] = '#'; // Start character
txd_buffer[pt++] = 'a' + address; // Address (a=0; b=1,...)
txd_buffer[pt++] = cmd; // Command
 
va_start(ap, numofbuffers);
if(numofbuffers)
{
pdata = va_arg(ap, uint8_t*);
len = va_arg(ap, int);
ptr = 0;
numofbuffers--;
}
 
while(len)
{
if(len)
{
a = pdata[ptr++];
len--;
if((!len) && numofbuffers)
{
pdata = va_arg(ap, uint8_t*);
len = va_arg(ap, int);
ptr = 0;
numofbuffers--;
}
}
else a = 0;
if(len)
{
b = pdata[ptr++];
len--;
if((!len) && numofbuffers)
{
pdata = va_arg(ap, uint8_t*);
len = va_arg(ap, int);
ptr = 0;
numofbuffers--;
}
}
else b = 0;
if(len)
{
c = pdata[ptr++];
len--;
if((!len) && numofbuffers)
{
pdata = va_arg(ap, uint8_t*);
len = va_arg(ap, int);
ptr = 0;
numofbuffers--;
}
}
else c = 0;
txd_buffer[pt++] = '=' + (a >> 2);
txd_buffer[pt++] = '=' + (((a & 0x03) << 4) | ((b & 0xf0) >> 4));
txd_buffer[pt++] = '=' + (((b & 0x0f) << 2) | ((c & 0xc0) >> 6));
txd_buffer[pt++] = '=' + ( c & 0x3f);
}
va_end(ap);
AddCRC(pt); // add checksum after data block and initates the transmission
}
 
 
// --------------------------------------------------------------------------
void Decode64(void)
{
uint8_t a,b,c,d;
uint8_t x,y,z;
uint8_t ptrIn = 3;
uint8_t ptrOut = 3;
uint8_t len = ReceivedBytes - 6;
 
while(len)
{
a = rxd_buffer[ptrIn++] - '=';
b = rxd_buffer[ptrIn++] - '=';
c = rxd_buffer[ptrIn++] - '=';
d = rxd_buffer[ptrIn++] - '=';
//if(ptrIn > ReceivedBytes - 3) break;
 
x = (a << 2) | (b >> 4);
y = ((b & 0x0f) << 4) | (c >> 2);
z = ((c & 0x03) << 6) | d;
 
if(len--) rxd_buffer[ptrOut++] = x; else break;
if(len--) rxd_buffer[ptrOut++] = y; else break;
if(len--) rxd_buffer[ptrOut++] = z; else break;
}
pRxData = &rxd_buffer[3];
RxDataLen = ptrOut - 3;
}
 
 
 
// --------------------------------------------------------------------------
int16_t USART0_putchar (int8_t c)
{
// if tx is not enabled return immediatly
if(!(UCSR0B & (1 << TXEN0))) return (0);
if (c == '\n') USART0_putchar('\r');
// wait until previous character was send
loop_until_bit_is_set(UCSR0A, UDRE0);
// send character
UDR0 = c;
return (0);
}
 
 
// --------------------------------------------------------------------------
void USART0_ProcessRxData(void)
{
// if data in the rxd buffer are not locked immediately return
if(!rxd_buffer_locked) return;
 
Decode64(); // decode data block in rxd_buffer
 
switch(rxd_buffer[1]-'a') // check Slave Address
{
case MK3MAG_ADDRESS:
 
switch(rxd_buffer[2]) // check for CmdID
{
case 'w': // old style
case 'k': // Attitude info from FC
memcpy(&ExternData, (uint8_t*)pRxData, sizeof(ExternData));
RequestFlags |= RQST_COMPASS_HEADING;
AttitudeSource = ATTITUDE_SOURCE_UART;
Orientation = ExternData.Orientation;
FC_Connected = 255;
break;
 
default:
// unsupported command
break;
} // case MK3MAG_ADDRESS:
 
default: // any Slave Adress
 
switch(rxd_buffer[2]) // check for CmdID
{
case 'b': // extern control
memcpy(&ExternControl, (uint8_t*)pRxData, sizeof(ExternControl));
#define KEY1 0x01
#define KEY2 0x02
#define KEY3 0x04
#define KEY4 0x08
#define KEY5 0x10
// use right arrow at display for switching the calstate
if(ExternControl.RemoteButtons & KEY2)
{
ExternData.CalState++;
if(ExternData.CalState == 6) ExternData.CalState = 0;
}
ConfirmFrame = ExternControl.Frame;
PC_Connected = 255;
break;
 
case 'd': // request for the debug data
DebugData_Interval = (uint16_t) pRxData[0] * 10;
if(DebugData_Interval>0) RequestFlags |= RQST_DEBUG_DATA;
PC_Connected = 255;
break;
 
case 'v': // request version and board release
RequestFlags |= RQST_VERSION_INFO;
PC_Connected = 255;
break;
 
case 'h': // request lcd data
PC_Connected = 255;
break;
 
case 'a':// Labels of the Analog Debug outputs
RequestDebugLabel = pRxData[0];
RequestFlags |= RQST_DEBUG_LABEL;
PC_Connected = 255;
break;
 
case 'g':// get extern control data
RequestFlags |= RQST_EXTERN_CTRL;
PC_Connected = 255;
break;
 
default:
// unsupported command
break;
}
break; // default:
}
// unlock the rxd buffer after processing
pRxData = 0;
RxDataLen = 0;
rxd_buffer_locked = FALSE;
}
 
 
 
//---------------------------------------------------------------------------------------------
void USART0_TransmitTxData(void)
{
if(!(UCSR0B & (1 << TXEN0))) return;
 
if(!txd_complete) return;
 
if((RequestFlags & RQST_DEBUG_LABEL) && txd_complete)
{
SendOutData('A', MK3MAG_ADDRESS, 2, (uint8_t *)&RequestDebugLabel, sizeof(RequestDebugLabel), (uint8_t *) ANALOG_LABEL[RequestDebugLabel], 16);
RequestDebugLabel = 0xFF;
RequestFlags &= ~RQST_DEBUG_LABEL;
}
 
if(ConfirmFrame && txd_complete)
{
SendOutData('B', MK3MAG_ADDRESS, 1, (uint8_t *) &ConfirmFrame, sizeof(ConfirmFrame));
ConfirmFrame = 0;
}
 
if(( (DebugData_Interval>0 && CheckDelay(DebugData_Timer)) || (RequestFlags & RQST_DEBUG_DATA)) && txd_complete)
{
SetDebugValues();
SendOutData('D', MK3MAG_ADDRESS, 1, (uint8_t *) &DebugOut, sizeof(DebugOut));
DebugData_Timer = SetDelay(DebugData_Interval);
RequestFlags &= ~RQST_DEBUG_DATA;
}
 
 
if((RequestFlags & RQST_EXTERN_CTRL) && txd_complete)
{
SendOutData('G', MK3MAG_ADDRESS, 1, (uint8_t *) &ExternControl,sizeof(ExternControl));
RequestFlags &= ~RQST_EXTERN_CTRL;
}
 
if((RequestFlags & RQST_COMPASS_HEADING) && txd_complete)
{
SendOutData('K', FC_ADDRESS, 1, (uint8_t *) &I2C_Heading, sizeof(I2C_Heading)); // send compass heading to FC
RequestFlags &= ~RQST_COMPASS_HEADING;
}
 
if((RequestFlags & RQST_VERSION_INFO) && txd_complete)
{
SendOutData('V', MK3MAG_ADDRESS, 1, (uint8_t *) &UART_VersionInfo, sizeof(UART_VersionInfo));
RequestFlags &= ~RQST_VERSION_INFO;
}
}
 
 
void USART0_Print(int8_t *msg)
{
uint8_t i = 0;
while(msg[i] != 0)
{
USART0_putchar(msg[i++]);
}
}
/tags/V0.21b/uart.h
0,0 → 1,76
#ifndef _UART_H_
#define _UART_H_
 
#include <inttypes.h>
 
#define NICK 0
#define ROLL 1
 
 
#define BAUD_RATE 57600
 
 
extern uint16_t DebugData_Timer;
 
 
void USART0_Init (void);
void USART0_EnableTXD(void);
void USART0_DisableTXD(void);
void USART0_TransmitTxData(void);
void USART0_ProcessRxData(void);
int16_t USART0_putchar(int8_t c);
void USART0_Print(int8_t *msg);
 
 
 
typedef struct
{
uint8_t Digital[2];
uint16_t Analog[32]; // Debugvalues
} DebugOut_t;
 
extern DebugOut_t DebugOut;
 
 
 
typedef struct
{
int16_t Attitude[2]; // nick and roll angle in 0.1 deg
uint8_t UserParam[2];
uint8_t CalState;
uint8_t Orientation;
} ExternData_t;
 
extern ExternData_t ExternData;
 
typedef struct
{
uint8_t Digital[2];
uint8_t RemoteButtons;
int8_t Nick;
int8_t Roll;
int8_t Yaw;
uint8_t Gas;
int8_t Height;
uint8_t free;
uint8_t Frame;
uint8_t Config;
} ExternControl_t;
 
extern ExternControl_t ExternControl;
 
 
typedef struct
{
uint8_t SWMajor;
uint8_t SWMinor;
uint8_t ProtoMajor;
uint8_t ProtoMinor;
uint8_t SWPatch;
uint8_t Reserved[5];
} UART_VersionInfo_t;
 
extern uint8_t PC_Connected;
extern uint8_t FC_Connected;
 
#endif //_UART_H_
/tags/V0.21b
Property changes:
Added: tsvn:logminsize
+8
\ No newline at end of property