Subversion Repositories Projects

Compare Revisions

Ignore whitespace Rev 1114 → Rev 1115

/NGVideo5_8/tags/v1.11/Hexfiles/NGVideo_MEGA644.hex
0,0 → 1,1630
:100000000C9467050C94B9070C94F0070C948405C4
:100010000C9484050C9484050C9484050C9484053C
:100020000C9484050C9484050C9484050C944D0761
:100030000C9484050C9419290C9484050C94840563
:100040000C9484050C9484050C946D250C94840503
:100050000C94C7290C9484050C9484050C94840595
:100060000C9484050C9484050C9484050C948405EC
:10007000084AD73B3BCE016E84BCBFFDC12F3D6C0F
:1000800074319ABD56833DDA3D00C77F11BED9E475
:10009000BB4C3E916BAAAABE000000803F05A84C55
:1000A000CDB2D44EB93836A9020C50B99186880821
:1000B0003CA6AAAA2ABE000000803F525353492DF5
:1000C0004D696E00525353492D4D61780044697655
:1000D000657273697479004C4344004156310041A4
:1000E000563200312E52583A00322E52583A0032CF
:1000F0003535003130323300536572766F20310070
:10010000536572766F20320052535349004D4B2D88
:10011000436F636B70697400536572766F2D487915
:10012000737465722E00426175647261746500209B
:10013000203556004E472D566964656F2020352EB8
:100140003847487A0A48573A200020204D2E426509
:10015000636B46573A20312E31302020676562614B
:1001600064005370726163686500446575747363FD
:100170006800456E676C69736368004672616E7AE9
:10018000947369736368005A757281636B0041569A
:100190002D5175656C6C650052582D4B616E616C0C
:1001A00000525353492D4B616C6962722E004269B3
:1001B00074746520545820617566200041555300C1
:1001C00045494E00576569746572206D6974204514
:1001D0006E746572004B6F6E7472617374004C4381
:1001E000442D42656C65756368742E004C696368C4
:1001F000743A0020696D6D65722061757300206925
:100200006D6D65722065696E002053656B2E00422E
:100210006174746572696500552D4D696E00556E87
:1002200074657273702E2D536574757000552D4F63
:100230006666736574004B616C696272696572759C
:100240006E67006C84756674004665686C65722123
:100250000053656E646572206E69636874200020C7
:100260002020202020416B6B750A20202020656E05
:10027000746C6164656E2100536572766F2D4B61FD
:100280006C6962722E00536572766F2D53636872CB
:100290006974746500536572766F203120726576DB
:1002A0002E004B616C69622E31206C696E6B73009D
:1002B0004B616C69622E3120726563687473004B08
:1002C000616C69622E31204D6974746500536572EA
:1002D000766F2032207265762E004B616C69622E3B
:1002E00032206C696E6B73004B616C69622E322038
:1002F000726563687473004B616C69622E32204DC5
:1003000069747465006175730065696E00416E748F
:10031000656E6E65206E616368662E0047505320DF
:100320006D6974207769323332005458204F53443A
:100330002D446174656E00487973746572657365E8
:100340000053656E646520466F72646572756E67F2
:10035000004750532D416E7A656967656E0062658E
:10036000726563686E2E20446174656E00616B7403
:1003700075656C6C6520506F732E005374617274D8
:10038000706F736974696F6E0020202020204E6F9B
:1003900063680A20206B65696E6520446174656E30
:1003A0000A202020656D7066616E67656E210052BF
:1003B000582D5A6569740053657269656C6C2043E9
:1003C0004F4D002C00332C3356004C616E67756125
:1003D0006765004765726D616E00456E676C697395
:1003E00068004672656E63680052657475726E00CF
:1003F00041562D536F757263650052582D436861E5
:100400006E6E656C00525353492D43616C69627284
:100410002E0054582073776974636820004F464655
:10042000004F4E00436F6E74696E756520456E74A3
:10043000657200436F6E7472617374004261636B26
:1004400067722E204C69676874004C696768743A5B
:1004500000616C77617973206F66660020616C774C
:10046000617973206F6E00207365632E00426174A2
:100470007465727900552D4D696E004C6F7720764A
:100480006F6C7461676500552D4F66667365740007
:1004900043616C6962726174696F6E0072756E6E31
:1004A000696E67004572726F7221005472616E73DB
:1004B0006D6974746572206E6F7420002020202096
:1004C0002020416363750A2020202020206C6F7754
:1004D0002100536572766F2D43616C6962722E0044
:1004E000536572766F2D5374657073005365727621
:1004F0006F2031207265762E0043616C69622E3167
:10050000206C6566740043616C69622E31207269EB
:100510006768740043616C69622E31206D696464A0
:100520006C6500536572766F2032207265762E00FE
:1005300043616C69622E32206C6566740043616CA5
:1005400069622E322072696768740043616C696267
:100550002E32206D6964646C65006F6666006F6E94
:100560002000547261636B696E67004750532077B7
:10057000697468207769323332005458204F5344ED
:100580002D44617461004879737465726573650008
:100590005472616E736D69742064656D616E640080
:1005A000446973706C6179204750530063616C63D8
:1005B0002E20446174610063757272656E74205000
:1005C0006F732E00486F6D65706F736974696F6E1D
:1005D00000202020204E6F74207965740A2020208E
:1005E0002020446174610A20202072656365697669
:1005F0006564210052582D54696D65005365726918
:10060000656C6C20434F4D002E00332E3356004C4A
:10061000616E67756500416C6C656D616E6400416B
:100620006E676C616973004672616E876169730001
:100630005265746F75720041562D536F7572636504
:100640000052582D43616E616C00525353492D4343
:10065000616C6962722E0000457465696E64726532
:1006600020547800416C6C756D657220547800419F
:1006700070702E20456E74657200436F6E747261E7
:1006800073746500526574722E2045636C00456377
:100690006C61693A0020457465696E740020546A83
:1006A0007273204F4E00205365632E0042617474B4
:1006B0006572696500562D4D696E00536575696CEC
:1006C00020416C61726D6500562D4F6666736574CE
:1006D0000043616C6962726174696F6E00456E20DF
:1006E000636F7572730045727265757221004E6F8B
:1006F000205478002020202042617474657269655E
:100700000A20202020666169626C652100536572B1
:10071000766F2D43616C696272004E62726520646F
:10072000652050617300496E766572732E205365A3
:1007300072766F310043616C2E2047617563686586
:100740000043616C2E2044726F6974650043616CD4
:100750002E2043656E74726500496E766572732E45
:1007600020536572766F320043616C2E20476175AD
:100770006368650043616C2E2044726F6974650084
:1007800043616C2E2043656E747265004F464600CF
:100790004F4E2000547261636B696E67004750537F
:1007A0002077697468207769323332005458204FBB
:1007B00053442D44617461004879737465726573A4
:1007C000697300446F6E6E8265205472616E736D42
:1007D00069650041666669636861676520475053D3
:1007E0000043616C63756C2047505300506F732E4B
:1007F0002061637475656C6C6500486F6D65706F22
:10080000736974696F6E0020417563756E6520644D
:100810006F6E6E82650A20202020207265877565C4
:10082000210052582D54656D707300434F4D2E209A
:100830005382726965002E00332E33560062016ABE
:100840000172017B0187018E019801A101AE01BCFB
:1008500001C001C401D501DE01EC01F301FE010973
:10086000020F0218021E022D0236024302490251F3
:10087000025F02780286029502A202B002BF02CD98
:1008800002DA02E802F702050309030D031C032A3A
:10089000033703410351035E036D037B038903AFF9
:1008A00003B703C303C503CA03D303DA03E203E9AF
:1008B00003F003FA03050412041D04210424043385
:1008C000043C044A0451045C0467046D0475047B11
:1008D00004870490049C04A404AB04BC04D204E088
:1008E00004EC04F90406051405230530053D054B09
:1008F000055A055E0562056B057A0586059005A01B
:1009000005AC05B705C405D105F405FC0508060AC4
:10091000060F0616061F0627063006370641064A4A
:10092000065706580664066F067A0684068E0695F4
:10093000069D06A606AC06B506BB06C806D106DDB2
:1009400006E606EE06F4060D071A072607350741E8
:10095000074D0759076807740780078C07900794AD
:10096000079D07AC07B807C307D307E107EC07FAF1
:1009700007070822082B0836083808BB00C400CD3A
:1009800000D700DB00DF00E300E900EF00F300F830
:1009900000000108010D01180126012F0134014A50
:1009A000013000303100303200303300303331005C
:1009B00030333200303400303500303531003035DE
:1009C000320030353231003035323200303532339A
:1009D00000303532340030353300303533310030BB
:1009E0003533320030353333003035333400303670
:1009F00000303631003036320030370030373100C9
:100A000030373200303800303900303A00303A3177
:100A100000303A3200303A3300303A3400A1095203
:100A200022A3097020A6090C20A9093222AC094290
:100A300023B009F722B409C21FB7091222BA0970FC
:100A40001FBE09ED21C2096A1FC709E41ECC094275
:100A50001ED109A21DD609C721DA09641FDF09DEEC
:100A60001EE4093C1EE9099C1DEE09A721F109C5F8
:100A70001CF5096D1CF9098721FC090A1C000AC331
:100A80001B040A471B070A361B0A0A64210D0ACCFD
:100A900022110ACC22150ACC22190A9C22202010ED
:100AA0001010102020202018181818202020201C9A
:100AB0001C1C1C202020201E1E1E1E202020201F4B
:100AC0001F1F1F20200608141314080620001124DD
:100AD0001FBECFEFD0E1DEBFCDBF12E0A0E0B1E09E
:100AE000EEE7F4E602C005900D92A633B107D9F700
:100AF00014E0A6E3B2E001C01D92AE33B107E1F706
:100B00000E948D230C943D320C9400008150282FBC
:100B1000277092B1922B92B995B1292B25B9886F84
:100B200092B1982392B995B1892385B90895149803
:100B30001092C4020895149A81E08093C40208952B
:100B4000982F813041F0813018F0823089F40AC04A
:100B50008DB38C7F09C08DB38C7F8DBB149A90931D
:100B6000C40206C08DB383608DBB14981092C4027A
:100B7000892F0895109236022F9808958091360299
:100B80008823B1F480918601882391F02091BC02E2
:100B90003091BD0290E02817390750F4F894109274
:100BA000BD021092BC02789481E0809336022F9AA5
:100BB000089580913602813009F5409186014423E1
:100BC00021F4109236022F9808954F31B8F4F8941A
:100BD0008091BC029091BD0201969093BD028093DA
:100BE000BC0278942091BC023091BD02842F90E029
:100BF0002817390718F0109236022F98089580E4CC
:100C000080937C0087E080937A0080917A008068EE
:100C100080937A0080917A00806480937A0080913A
:100C20007A0086FDFCCF809178009091790008953C
:100C300090917C008F71907E892B80937C008091B5
:100C40007A00806480937A0080917A0086FDFCCFE0
:100C50002091780030917900C90108959F92AF9258
:100C6000BF92CF92DF92EF92FF920F931F93CF9399
:100C7000DF93982E6B01EE24FF248701C0E0D0E0C3
:100C800088E8A82E83E1B82E0DC0892D0E94180691
:100C9000A0E0B0E0E80EF91E0A1F1B1FC501019776
:100CA000F1F72196CC15DD0580F3960140E050E088
:100CB000C801B7010E94F030C901DF91CF911F91A7
:100CC0000F91FF90EF90DF90CF90BF90AF909F90EB
:100CD0000895AF92BF92CF92DF92EF92FF920F935F
:100CE0001F932C9A90E0A0E0B0E0BC01CD010E94DF
:100CF0007A2E5B016C0120E030E44CE955E40E945F
:100D0000F12F7B018C0120E030E040E85FE30E949E
:100D1000DA2D88231CF461E070E024C0C801B7011B
:100D200020E03FEF4FE757E40E94E62F1816B4F497
:100D3000C601B50120E030E040E251E40E94F12F0D
:100D40000E944E2E84EF91E005C0FC013197F1F72F
:100D50006150704061157105C1F707C0C801B70146
:100D60000E944E2ECB010197F1F72C981F910F9105
:100D7000FF90EF90DF90CF90BF90AF9008959F923B
:100D8000AF92BF92CF92DF92EF92FF920F931F9399
:100D9000982EE62E0E946906FF2400E010E0C801AC
:100DA000B7010E947A2E5B016C0120E030E44CE92F
:100DB00055E40E94F12F7B018C0120E030E040E8F7
:100DC0005FE30E94DA2D88231CF461E070E024C008
:100DD000C801B70120E03FEF4FE757E40E94E62F3C
:100DE0001816B4F4C601B50120E030E040E251E449
:100DF0000E94F12F0E944E2E84EF91E005C0FC016D
:100E00003197F1F76150704061157105C1F707C066
:100E1000C801B7010E944E2ECB010197F1F7892D31
:100E20000E9469061F910F91FF90EF90DF90CF9085
:100E3000BF90AF909F900895CF93DF93EC01809186
:100E40008E0190918F010F97209190013091910127
:100E5000821B930B6BE070E00E94DC30A62FB0E0A9
:100E600040E050E020E030E0FE01E20FF31F80910F
:100E70008E0190918F01841B950B918380834A0F83
:100E80005B1F2E5F3F4F2831310571F7862F65E0DC
:100E90000E94D030DF91CF9108951F920F920FB62C
:100EA0000F9211242F938F939F93AF93BF9384E658
:100EB0008093B2008091EC028F3F29F08091EC0288
:100EC0008F5F8093EC028091AB028F3F29F080917D
:100ED000AB028F5F8093AB028091D3029091D402DA
:100EE0008C5E944048F48091D3029091D402019694
:100EF0009093D4028093D30280913802823079F5A6
:100F000080913B02882359F18091C4028823A1F08B
:100F10008091400290914102A0914202B09143021F
:100F20000196A11DB11D8093400290934102A093B0
:100F30004202B093430213C080913C0290913D0263
:100F4000A0913E02B0913F020196A11DB11D809378
:100F50003C0290933D02A0933E02B0933F02BF91AA
:100F6000AF919F918F912F910F900FBE0F901F9077
:100F700018951F920F920FB60F9211248F939F9383
:100F80008091EC028F3438F08091EC02823518F4B5
:100F90001092B0020AC091E09093B0028091EE02EC
:100FA000882319F4149A9093C4029091B00280910E
:100FB000EE02981761F48091CA02882321F41498F4
:100FC0001092C40204C0149A81E08093C40210926B
:100FD000EC029F918F910F900FBE0F901F9018956C
:100FE0001F920F920FB60F9211248F939F938091AF
:100FF000AB028F3438F08091AB02823518F4109236
:10100000EE020AC081E08093EE028091B002882354
:1010100019F414981092C4029091B0028091EE02DB
:10102000981761F48091CA02882321F414981092D1
:10103000C40204C0149A81E08093C4021092AB02EF
:101040009F918F910F900FBE0F901F9018950E9447
:10105000BE0580918703882331F0F89410928703AE
:1010600078940E94D90508954F925F926F927F9273
:101070008F929F92AF92BF92CF92DF92EF92FF92A8
:101080000F931F93CF93DF93EC013A014B01122F83
:10109000CB01BA012CE330E040E050E00E94F03098
:1010A0005B016C01412E552447FC5094C40DD51DA5
:1010B000EE24FF24012F10E00150104018C0B501AC
:1010C000C6012AE030E040E050E00E94F030605D70
:1010D0006883B501C6012AE030E040E050E00E949C
:1010E000F03059016A010894E11CF11C2197C201FA
:1010F0008E199F098017910714F7C401B3012CE3DF
:1011000030E040E050E00E94F030CA01B901DF91C8
:10111000CF911F910F91FF90EF90DF90CF90BF90F4
:10112000AF909F908F907F906F905F904F900895B9
:101130001F9310913802109238020E94772680E0A7
:1011400060E00E94D824812F1F9108950F931F9370
:10115000DF93CF93CDB7DEB729970FB6F894DEBFF4
:101160000FBECDBF20EA3FE040E050E00E94F030EB
:10117000BA0119868E010F5F1F4FC801A90127E030
:101180000E943408AB01BC01C80124E00E9434086D
:10119000AB01BC01C80121E00E9434088AE38B83C3
:1011A0008E83C8010E94E62429960FB6F894DEBF0C
:1011B0000FBECDBFCF91DF911F910F91089586E0B3
:1011C00061E00E94D82460913C0270913D028091C0
:1011D0003E0290913F020E94A60886E062E00E94D3
:1011E000D824609140027091410280914202909116
:1011F00043020E94A60808958091F002813021F4F4
:101200001092F00280E104C081E08093F0028CE053
:101210008093BE0286E090E06091F0020E9412325C
:1012200087E090E06091BE020E94123208958091A2
:101230003802833061F4E091A501F0E0EE0FFF1F6A
:10124000EE0FFF1FEA59FE4F8081918104C080910B
:101250007E0190917F010E94952908950E94DB26CE
:10126000BC017695679580E00E94C42781E060E02C
:1012700070E00E94C4270895DF92EF92FF920F93CF
:101280001F93D82E7B010E94DB260027F7FC0095D8
:10129000102F9C0140E050E0C801B7010E94B1301E
:1012A00024EB30E040E050E00E94F0308D2DB90199
:1012B0000E94C4271F910F91FF90EF90DF90089537
:1012C0000F931F93CF93DF9385E00E941806A0E051
:1012D000B0E0209192013091930140E050E0BC01D8
:1012E000CD010E94B13047E0969587957795679537
:1012F0004A95D1F7EB0186E00E941806A0E0B0E025
:10130000209194013091950140E050E0BC01CD0165
:101310000E94B13037E096958795779567953A9515
:10132000D1F7809189028823B1F4C617D70740F41A
:101330008091870290918802009711F101971CC05B
:101340008091A401680F711D6C177D0750F581E035
:101350008093890226C06C177D07D0F40091870224
:10136000109188020E94DB260817190748F4809123
:101370008702909188020196909388028093870259
:10138000609187027091880280E00E94C42709C0A2
:101390008091A401C80FD11DC617D70710F4109271
:1013A0008902DF91CF911F910F910895EF92FF92E3
:1013B0000F931F93CF93DF93E82EC6E9D1E00AE1A4
:1013C00010E0FF2429813A814B815C818D819E81CF
:1013D000EE2089F436952795369527953A8329830B
:1013E00056954795569547955C834B83969587957B
:1013F0009695879511C0220F331F220F331F3A8312
:101400002983440F551F440F551F5C834B83880F5E
:10141000991F880F991F03969E838D8369817A8116
:101420008F2D0E94F7266B817C818F2D0E941427BF
:101430006D817E818F2D0E943327CE01B80147E058
:1014400050E00E940832F39427960F5C1F4F82E011
:10145000F81609F0B7CF0E942E09DF91CF911F91A6
:101460000F91FF90EF9008950F931F93182F062F61
:10147000823078F462E0681B8FE00E94D82480E21A
:101480000E9467241F5F8FE0612F0E94D824802F65
:101490000CC08FE061E00E94D82480E20E946724A3
:1014A0008FE062E00E94D82480E20E9467241F91AE
:1014B0000F910895EF92FF920F931F93DF93CF93B5
:1014C000CDB7DEB72E970FB6F894DEBF0FBECDBFF7
:1014D0007B018C01DE011196E2E1F2E08EE00190E9
:1014E0000D928150E1F78E2D805D0E94672480E08F
:1014F00091E00E94E6240894E108F108010911092D
:10150000F701EE0FFF1FEC0FFD1F818192810E94FA
:10151000E62483E091E00E94E6242E960FB6F8942C
:10152000DEBF0FBECDBFCF91DF911F910F91FF9016
:10153000EF900895EF92FF920F931F93F82EE92EEC
:10154000062F80E00E94D82410E080E20E946724E9
:101550001F5F1031D1F7EF2DFE2DDF010D90002020
:10156000E9F7EA1BFB0B7196F695E7958E2F602F36
:101570000E94D8248F2D9E2D0E94E6241F910F914A
:10158000FF90EF900895AF92BF92CF92DF92EF92CB
:10159000FF920F931F93DF93CF93CDB7DEB72C97B6
:1015A0000FB6F894DEBF0FBECDBF6C018E010F5F8A
:1015B0001F4F5C0178012BE0A4E07FEFA03241F0E7
:1015C000F501808191818417950710F4272FA0E2FF
:1015D000F701A1937F017F5F82E090E0A80EB91E22
:1015E0007B3061F72F3FC1F0332727FD3095F9019C
:1015F000EE0FFF1FEC0DFD1D80819181841B950B6B
:1016000070E00E94DC30FE013196E20FF31F608330
:10161000653010F084E080838DE0E82EF12CEC0E34
:10162000FD1EF80181918F010E9467240E151F0590
:10163000C1F72C960FB6F894DEBF0FBECDBFCF9189
:10164000DF911F910F91FF90EF90DF90CF90BF90AF
:10165000AF900895CF92DF92EF92FF920F931F9376
:10166000CF93DF93082F6B01142F85E00E9418069B
:10167000A0E0B0E0209192013091930140E050E071
:10168000BC01CD010E94B13037E0969587957795E2
:1016900067953A95D1F77B0186E00E941806A0E095
:1016A000B0E0209194013091950140E050E0BC0100
:1016B000CD010E94B13027E0969587957795679583
:1016C0002A95D1F7EB01023001F5E616F70670F422
:1016D000109275028091EC028F3FC9F48091AB02A9
:1016E0008F3FA9F414981092C40211C091E0909316
:1016F00075028091EC028F3F51F48091AB028F3FD5
:1017000031F4149A9093C40202C00093750211231D
:1017100009F447C0023011F01BEF1EC09091B002D7
:101720008091EE02981799F09091EC028091AB02B3
:1017300089238F3F61F08091B002882319F41092C1
:10174000760203C081E08093760213E705C08091A2
:1017500075028093760214E6F601808191818E15E0
:101760009F0520F48C179D0708F410E282E061E0E9
:101770000E94D824C6016091C202A7010E94C30A38
:1017800082E062E00E94D824C6016091C202AE01EC
:101790000E94C30A023029F480917602612F0E94D0
:1017A000340A80917502DF91CF911F910F91FF90C4
:1017B000EF90DF90CF9008958091BF02882381F051
:1017C000F8941092BF0278946091A6017091A701DD
:1017D000809137024091A8010E942A0B8093CA028F
:1017E00008958091A801882341F18091A90188235F
:1017F00021F581E060E00E94D8248091B502882321
:1018000071F080918602863010F485E009C08091E5
:1018100023038A3010F088E503C0805D01C08AE3AD
:101820000E9467241092B502809186028F5F809398
:1018300086028C3011F4109286020895CF92DF92C6
:10184000EF92FF920F937A0169010E94D824C70199
:101850000E94E624C6010E94E624002319F0802F8E
:101860000E9467240F91FF90EF90DF90CF90089532
:101870000F931F93DF93CF93CDB7DEB727970FB6A4
:10188000F894DEBF0FBECDBFDC01CB01880F991FDE
:10189000880F991F8A599E4FFC0160817181828156
:1018A00093818E010F5F1F4FA8012AE030E00E9454
:1018B000B031C80161E00E949A0A27960FB6F894E9
:1018C000DEBF0FBECDBFCF91DF911F910F91089565
:1018D0004F925F926F927F928F929F92AF92BF9240
:1018E000CF92DF92EF92FF920F931F93DF93CF93EC
:1018F00000D000D0CDB7DEB72B013C0129833A835D
:101900004B835C83DF88B88C80E40E942126882387
:1019100029F480E40E942C268823E1F04E145F0411
:101920006006710648F40894411C511C611C711C2E
:101930008B2D0E945D2606C0DD2021F049805A8053
:101940006B807C808C2D6A2D0E94D824C301B2014B
:10195000F401099580E80E942126882329F480E873
:101960000E942C268823F1F089819A81AB81BC8169
:1019700084159505A605B70548F408944108510853
:10198000610871088B2D0E945D2604C0DD2011F0D6
:10199000270138018C2D6A2D0E94D824C301B20181
:1019A000F4010995B201C3010F900F900F900F90B1
:1019B000CF91DF911F910F91FF90EF90DF90CF902B
:1019C000BF90AF909F908F907F906F905F904F905F
:1019D00008950F931F93CF93DF938C01FC018081B7
:1019E000882309F1C0E0D0E0FE01EE0FFF1FEE0FEB
:1019F000FF1FE35EF54F65917491C8010E94643149
:101A0000892B69F4CE01880F991F880F991F815E79
:101A1000954FFC0125913491F901099504C0219657
:101A2000C032D10509F7DF91CF911F910F91089531
:101A30001F93182F8091AD02882319F060E070E0A9
:101A400005C00E94DB26BC01769567958091AD02AA
:101A50000E94C42710933802112389F420E044EF38
:101A600051E008C0FA013197F1F70197D9F72F5FDC
:101A7000223019F080ED97E0F5CF0E94BE2789EA69
:101A800091E00E94E90C1F9108958533910540F083
:101A9000FC01EE0FFF1FEF5EF64F659174911CC0C5
:101AA00020918D01213029F0880F991F223079F47F
:101AB00008C0FC01EE0FFF1FE955F74F65917491C7
:101AC0000BC0FC01EF5EF64F6591749105C0FC01FF
:101AD000E35CF74F6591749184E492E00E946D316C
:101AE00084E492E00895DF93CF9300D00F92CDB7B6
:101AF000DEB7DE011196EBEDF1E023E001900D92EF
:101B00002150E1F7FE01E60FF71F818190E00E946E
:101B1000450D61E00E949A0A0F900F900F90CF91AF
:101B2000DF910895DF93CF9300D0CDB7DEB72DE3DB
:101B300029832EE32A83FE01E60FF71F818190E0BF
:101B40000E94450D61E00E949A0A0F900F90CF917C
:101B5000DF910895611571058105910519F485E2FC
:101B600090E002C086E290E00E94450D0E94E624CB
:101B70000895DF92EF92FF920F931F93DF93CF931D
:101B800000D000D00F92CDB7DEB77B018C018EE084
:101B900090E00E94450DFC0101900020E9F731978B
:101BA000DE2ED81AE114F1040105110539F08FE198
:101BB000E816F1040105110529F510C08FE090E049
:101BC0000E94450DFC0101900020E9F73197E81BC8
:101BD000F90B1D2D1E0F8FE090E00FC080E190E00B
:101BE0000E94450DFC0101900020E9F73197E81BA8
:101BF000F90B1D2D1E0F80E190E00E94450D0E9403
:101C0000E62437C0C801B7012AE030E040E050E0E8
:101C10000E94B130DC01CB017E010894E11CF11C73
:101C2000B7014AE050E00E948F3180E20E946724B1
:101C3000C7010E94E62481E190E00E94450D0E94C8
:101C4000E624F70101900020E9F78F0101501040D0
:101C50000E191F0981E190E00E94450DDC010D90F5
:101C60000020E9F71197A81BB90B1D2D100F1F5F5E
:101C70001A0F00E1011B10E004C080E20E946724FB
:101C80001F5F1017D0F30F900F900F900F900F90D1
:101C9000CF91DF911F910F91FF90EF90DF9008950A
:101CA000DF93CF9300D0CDB7DEB725E229832BE2B7
:101CB0002A83FE01E60FF71F818190E00E94450D07
:101CC00061E00E949A0A0F900F90CF91DF910895E2
:101CD000DF93CF9300D000D0CDB7DEB725E22983C4
:101CE00021E42A8328E22B8322E42C83FE01E60FE1
:101CF000F71F818190E00E94450D61E00E949A0AE1
:101D00000F900F900F900F90CF91DF910895DF9378
:101D1000CF9300D00F92CDB7DEB7DE011196ECEE77
:101D2000F1E023E001900D922150E1F7FE01E60F72
:101D3000F71F818190E00E94450D61E00E949A0AA0
:101D40000F900F900F90CF91DF91089580E060E0A9
:101D50000E94D82486E490E00E94450D0E94E6246B
:101D60008091F002882319F484E390E002C085E4B6
:101D700090E00E94450D0E94E62487E490E00E94D6
:101D8000450D0E94E62420E044EF51E008C0FA012E
:101D90003197F1F70197D9F72F5F2F3119F088EEBE
:101DA00093E0F5CF0E94B72408950F931F93082F57
:101DB00090E00E94450DFC0101900020E9F7319769
:101DC000E81BE031D8F480E190E08E1B91099595F5
:101DD0008795182F823098F0825060E00E94D824B6
:101DE00087E091E00E94E624802F90E00E94450D5C
:101DF0000E94E62480E20E94672416C010E080E082
:101E000060E00E94D8248AE20E946724812F60E06B
:101E10000E94D824802F90E00E94450D0E94E62465
:101E20008FE060E00E94D8248AE20E9467241F911C
:101E30000F910895CF92DF92EF92FF920F931F932D
:101E4000CF93DF93EC01D42E662311F4F42E02C05D
:101E5000F62EFA94EE243EE0C32E82E06E2D0E9410
:101E6000D8248E010F0D111DF801808190E00E9491
:101E7000450D0E94E624F801808190E00E94450D06
:101E8000FC0101900020E9F73197E81BF90B0C2DBC
:101E90000E1B04C080E20E94672401501016D4F388
:101EA000FD1410F0FF2401C0F394E394F3E0EF1667
:101EB000A1F6DF91CF911F910F91FF90EF90DF90EE
:101EC000CF9008951F93182F0E94B72488E190E0C7
:101ED0000E94450D60E00E949A0A89E190E00E940C
:101EE000450D61E00E949A0A812F90E00E94450D05
:101EF00062E00E949A0A20E044EF51E008C0FA0133
:101F00003197F1F70197D9F72F5F2F3119F088EE4C
:101F100093E0F5CF1F9108950E94B72486E190E0E9
:101F20000E94450D60E00E949A0A87E190E00E94BD
:101F3000450D61E00E949A0A08952F923F924F92B8
:101F40005F926F927F928F929F92AF92BF92CF9249
:101F5000DF92EF92FF920F931F93DF93CF93CDB752
:101F6000DEB72B970FB6F894DEBF0FBECDBF5B0177
:101F70006C014B83122F402E5E2C83E390E00E9475
:101F8000450DFC0120812983D7FC02C01A820AC0BA
:101F9000D094C094B094A094A11CB11CC11CD11CBD
:101FA00031E03A835B81552321F080E3809379020D
:101FB00001C01150612E7724F301E758FD4F1182C3
:101FC00051105394812F992787FD909549E7842ECE
:101FD00042E0942E880E991EEE24FF249D838C836C
:101FE0009B81892F90E09F838E83830104191109BF
:101FF0001801250C311CD801A758BD4FB987A887F7
:1020000036C0EA85FB850E171F0739F4442029F0F6
:10201000E981A885B985EC9319C0C601B5012AE00C
:1020200030E040E050E00E941231605DD4016C93DA
:10203000C601B5012AE030E040E050E00E941231D4
:10204000C901DA015C016D01442059F0451448F0E2
:10205000EA85FB852E163F0621F4F101E758FD4F76
:1020600010820894E11CF11C0894810891082C81CD
:102070003D812E193F093B872A878E819F81281732
:1020800039070CF0BECFE9E7F2E020E030E04DE2A6
:1020900090E213C0AB81AA2351F0BA81BB2339F07F
:1020A000803321F482815981851709F440832F5FA1
:1020B0003F4F8081803341F491938181A9818A17B8
:1020C00019F02615370534F389E792E02B960FB601
:1020D000F894DEBF0FBECDBFCF91DF911F910F915E
:1020E000FF90EF90DF90CF90BF90AF909F908F9038
:1020F0007F906F905F904F903F902F900895AF9298
:10210000BF92CF92DF92EF92FF920F931F935B01EA
:102110006C017B010E94DB2696958795E81AF90AE7
:102120000027F7FC0095102FC801B70141E023E01C
:1021300000E0EE240E949D0F0E94E6248091AD02F3
:10214000B5010E9433271091AD020E94DB26BC012D
:1021500076956795812F0E94C4271F910F91FF905C
:10216000EF90DF90CF90BF90AF900895EF920F93D4
:1021700040E023E000E0EE240E949D0F0E94E62450
:102180000F91EF900895EF92FF920F931F93CF93CB
:10219000DF937B018C010E94DB26EC01C801B701B3
:1021A0000E94B6108091AD02B7010E9414272091C1
:1021B000AD02822F90E0FC0173E0EE0FFF1F7A95D5
:1021C000E1F7E81BF90BEA56FE4F8081882311F0F6
:1021D000C0E0D0E0822FBE010E94C427DF91CF91E2
:1021E0001F910F91FF90EF900895EF92FF920F9340
:1021F0001F937B018C010E94B6108091AD02B70144
:102200000E94F7268091AD0290E0FC01A3E0EE0F62
:10221000FF1FAA95E1F7E81BF90BEA56FE4F8081F4
:10222000882319F460E070E003C00E94DB26BC0143
:102230008091AD020E94C4271F910F91FF90EF90F3
:1022400008951F93162F0E94B6108091F002612FFF
:102250000E94BF241F910895EF920F9340E025E064
:1022600002E0B2E0EB2E0E949D0F0E94E62486E57C
:102270000E9467240F91EF900895EF920F9340E032
:1022800025E002E0EE24E3940E949D0F0E94E624E4
:102290000F91EF9008957F928F929F92AF92BF928D
:1022A000CF92DF92EF92FF920F931F93DF93CF9322
:1022B0000F92CDB7DEB7782E87E00E9418069C01FA
:1022C00040E050E060E070E080E090E000EFA02EA1
:1022D00019EAB12ECC24DD24EE24FF2400E010E026
:1022E0000E941A2B122FF32ED42EC52EB62EA72EF7
:1022F000982EE92E2091870130E040E050E060E028
:1023000070E080E090E00DE00E94942C892E210F77
:10231000E1E0211708F0E0E03F0DF1E03F1508F0A3
:10232000F0E0FE2EF30EE1E0F31608F0E0E0FE2B05
:102330004D0DA1E04D1508F0A0E00F2F040FE1E0D6
:10234000041708F0E0E0AE2B5C0DF1E05C1508F03E
:10235000F0E01A2F150FE1E0151708F0E0E0FE2B72
:102360006B0DA1E06B1508F0A0E0BF2FB60FE1E008
:10237000B61708F0E0E0AE2B7A0DF1E07A1508F020
:10238000F0E0A70FE1E0A71708F0E0E0FE2B890DD1
:1023900091E0891508F090E0F80FE1E0F81708F0F7
:1023A000E0E09E2BE80C3F2DA8016B2F7A2F8F2F9A
:1023B0009E0D0DE00E94152C79018A018091C502C5
:1023C0009091C602A091C702B091C8028E159F05D8
:1023D000A007B10708F443C08091A801882329F120
:1023E0008091880190918901A0918A01B0918B011F
:1023F0004496A11DB11D8093C5029093C602A0937F
:10240000C702B093C8020E94B7248AE190E00E94FC
:10241000450D0E94E6241092A80184E10E946906FD
:1024200080EF809377021092780281E0781689F528
:1024300080917802909177028F5F8093780281502B
:10244000891738F184E199830E9469069981933054
:1024500018F0969590937702109278021AC0209106
:1024600088013091890140918A0150918B01281790
:1024700039074A075B0768F481E08093A80120933D
:10248000C5023093C6024093C7025093C8020E940F
:102490007412B701C8010F90CF91DF911F910F9176
:1024A000FF90EF90DF90CF90BF90AF909F908F9074
:1024B0007F900895EF92FF920F931F9381E00E9407
:1024C0004B117B018C018091A801882341F08BE0A6
:1024D00060E00E94D824C801B7010E943D111F91FD
:1024E0000F91FF90EF9008950E94B7248091A8016A
:1024F0008823F9F00E94B72460918C0170E080E09D
:1025000090E00E945A0A8FE060E00E94D8248AE09E
:1025100091E00E94E62480913702823010F064E658
:1025200001C06BEF8091CA020E94340A0E945A12C5
:1025300008958AE190E00E94450D60E00E949A0AA9
:102540000895882361F08150E82FF0E0E755FE4FB1
:10255000908190539093B2021082882311F40E94CC
:10256000741208958091EB02882331F0F894109250
:10257000EB0278940E945A120895CF92DF92EF9264
:10258000FF920F931F93CF93DF936C01EB017B01BD
:1025900000E010E09C0140E050E08617970718F536
:1025A00097E0EE0CFF1C001F111F9A95D1F7C80190
:1025B000B7010E94F030CA01B9010E947A2E20E0D2
:1025C00030E040E05FE30E94142D0E944E2E709395
:1025D00093016093920180E890E09093950180933D
:1025E00094018E0124C087E0220F331F441F551F22
:1025F0008A95D1F7CA01B901A80197010E94F0306C
:10260000CA01B9010E947A2E20E030E040E05FE389
:102610000E94142D0E944E2E709395016093940198
:1026200080E890E0909393018093920186016091FD
:1026300092017091930185E190E00E9428326091AF
:1026400094017091950187E190E00E942832C801C1
:10265000DF91CF911F910F91FF90EF90DF90CF907E
:1026600008950F931F93CF93DF938C010E948C0FDB
:1026700085E068EE73E00E942E06EC0186E068EECD
:1026800073E00E942E06BC018C0F9D1F8059914063
:10269000B0F4CE010E94BD12BC01909391018093D1
:1026A000900183E190E00E94283284E06EE10E9474
:1026B000BF06C8010E941C078093C20203C08AE0C3
:1026C0000E94620FDF91CF911F910F9108950F9398
:1026D0001F93CF93DF938C010E948C0F85E068EEEF
:1026E00073E00E942E06EC0186E068EE73E00E9423
:1026F0002E06BC018C0F9D1F855F9140B0F0CE016E
:102700000E94BD12BC0190938F0180938E0181E1E4
:1027100090E00E94283284E06EE10E94BF06C8016A
:102720000E941C078093C20203C089E00E94620FCE
:10273000DF91CF911F910F910895EF92FF920F9328
:102740001F93DF93CF9300D000D00F92CDB7DEB7A9
:10275000082F80E090E00E94F431182F7E01089449
:10276000E11CF11CC70161E070E045E050E00E940F
:10277000E43188E893E10197F1F71B3499F40023E1
:1027800041F080E191E0B7010E947F31009709F4A8
:1027900085C080E191E0BE016F5F7F4F0E947F3175
:1027A0000097B9F080E090E06BE40E94123286E07E
:1027B00090E060E00E94123287E090E060E10E94C9
:1027C000123280E191E061E070E045E050E00E946B
:1027D000083288E090E06FE10E94123289E090E0D8
:1027E00065E50E9412328AE090E040EC53E060E040
:1027F00070E00E9420328EE090E061E00E94123290
:102800008FE090E060E00E94123280E190E06EEF95
:102810000E94123281E190E06CEC71E00E9428325B
:1028200083E190E06BE470E00E94283285E190E063
:1028300060E870E00E94283287E190E060E870E094
:102840000E94283289E190E060E00E94123286E91D
:1028500091E06AE170E047E050E00E9408328DE9C3
:1028600091E06BE470E047E050E00E9408328CE7B2
:1028700090E060E00E9412328DE790E068E20E94F2
:1028800012328EE790E060E00E9412328FE790E013
:1028900065E00E9412321092C00278C088E090E099
:1028A0000E94F4318093860189E090E00E94F43127
:1028B000809387018AE090E00E94FC316093880158
:1028C0007093890180938A0190938B018EE090E050
:1028D0000E94F43180938C018FE090E00E94F431EB
:1028E0008093370280E190E00E94F43180938D0163
:1028F00081E190E00E94023290938F0180938E01DB
:1029000083E190E00E9402329093910180939001C4
:1029100085E190E00E9402329093930180939201AE
:1029200087E190E00E940232909395018093940198
:1029300089E190E00E94F4318093C00286E991E041
:102940006AE170E047E050E00E94E4318DE991E0F7
:102950006BE470E047E050E00E94E4318CE790E0E7
:102960000E94F431809338028DE790E00E94F431A8
:102970008093A4018EE790E00E94F43180933902A5
:102980008FE790E00E94F4318093A50186E090E00B
:102990000E94F4318093F00287E090E00E94F431CD
:1029A0008093BE028091880190918901A0918A0153
:1029B000B0918B018093C5029093C602A093C70289
:1029C000B093C8028091A6019091A7010E941C07B4
:1029D0008093C202809137028093CA0280E06091A6
:1029E00096010E94E826609197017091980180E01D
:1029F0000E94F7266091990170919A0180E00E94EF
:102A0000142760919B0170919C0180E00E94332704
:102A100081E060919D010E94E82660919E01709185
:102A20009F0181E00E94F7266091A0017091A101B1
:102A300081E00E9414276091A2017091A30181E0BE
:102A40000E9433270E942E0981E08093B7020E94E2
:102A50001709809138020E94E92A0F900F900F9079
:102A60000F900F90CF91DF911F910F91FF90EF90FA
:102A700008951F93CF93DF9381EF92E062E00E946D
:102A8000F72A8823C9F18091F1028430A9F5809159
:102A9000F30290E09695982F882797958795209137
:102AA000F40230E0822B932B64E170E00E94DC3072
:102AB0006C33710518F4C0E0D0E007C0EB01EC976F
:102AC000C53BD10510F0C4EBD0E01091F2020E949A
:102AD000DB26A0E0B0E09E0140E050E0BC01CD016B
:102AE0000E94B13024EB30E040E050E00E94F03032
:102AF000812FB9010E94C427DF91CF911F910895C2
:102B00008091C9028823A9F0F8941092C9027894A0
:102B10006091A6017091A7018091370240E00E9468
:102B20002A0B8093CA0280913802833011F40E94EC
:102B3000391508951F938FE40E94832A882391F00A
:102B40008091D3029091D4028C5E944058F480918D
:102B5000350387FF07C080913403817080933B0267
:102B600011E001C010E080913902882359F0809172
:102B7000D3029091D402855A914020F085E191E0F2
:102B80000E94BA29812F1F9108952F923F924F9250
:102B90005F926F927F928F929F92AF92BF92CF92ED
:102BA000DF92EF92FF920F931F93DF93CF93CDB7F6
:102BB000DEB728970FB6F894DEBF0FBECDBF69A071
:102BC0007AA08BA09CA06FA978AD89AD9AAD0E9428
:102BD0007C2E20E836E948E15BE40E94E12D5B01B0
:102BE0006C01C401B301A60195010E94142D20E0DF
:102BF00030E040E05FE30E94F12F29E33AEF4EE836
:102C00005CE30E94F12F0E94DE2D20E032E649EDC8
:102C100057E40E94F12F7B018C016BA97CA98DA93F
:102C20009EA90E947C2E20E836E948E15BE40E94E0
:102C3000E12D9B01AC016D8D7E8D8F8D98A10E9441
:102C4000132D9B01AC01C801B7010E94F12F1B019C
:102C50002C01C401B301A60195010E94132D20E0AF
:102C600032E649ED57E40E94F12F5B016C01C2018D
:102C7000B101A60195010E94872D21EE3EE245E6B5
:102C800052E40E94F12F20E030E044E353E40E943C
:102C9000142D20E030E044EB53E40E94BE2E7B0173
:102CA0008C0137014801C801B70120E030E044EB56
:102CB00053E40E94E62F181654F4C801B70120E02F
:102CC00030E044EB53E40E94132D3B014C01C20160
:102CD000B101A20191010E94F12F7B018C01C6017B
:102CE000B501A60195010E94F12F9B01AC01C8011D
:102CF000B7010E94142D0E94583069837A838B8318
:102D00009C836D827E828F82988629813A814B8155
:102D10005C816D817E818F81988528960FB6F894AD
:102D2000DEBF0FBECDBFCF91DF911F910F91FF90FE
:102D3000EF90DF90CF90BF90AF909F908F907F905B
:102D40006F905F904F903F902F900895AF92BF92F9
:102D5000CF92DF92EF92FF920F931F93DF93CF9367
:102D6000CDB7DEB728970FB6F894DEBF0FBECDBF44
:102D70000E949A15882309F485C18091B70288239F
:102D800009F463C08091340383FF7CC1A0901003D9
:102D9000B0901103C0901203D0901303C601B50187
:102DA0000E947C2E20E836E948E15BE40E94E12D98
:102DB0006093D5027093D6028093D7029093D80285
:102DC000E0901403F090150300911603109117037F
:102DD000C801B7010E947C2E20E836E948E15BE497
:102DE0000E94E12D6093D9027093DA028093DB0296
:102DF0009093DC02A092DD02B092DE02C092DF026C
:102E0000D092E002E092E102F092E2020093E3024B
:102E10001093E4028091180390911903A0911A0372
:102E2000B0911B038093E5029093E602A093E70222
:102E3000B093E80280912F03909130039093EA02BF
:102E40008093E9021092B7021DC18DB79EB7839798
:102E50000FB6F8949EBF0FBE8DBF2DB73EB72F5F44
:102E60003F4FD901E5EDF2E086E101900D928150EE
:102E7000E1F7D9015696E2EFF2E08DE001900D9274
:102E80008150E1F70E94C51529833A834B835C8307
:102E90006D837E838F839887ABECB2E0FE01319621
:102EA00088E001900D928150E1F76091FA027091F3
:102EB000FB028091FC029091FD022091E50230918D
:102EC000E6024091E7025091E802621B730B840B0B
:102ED000950B0E947C2E20E030E04AE754E40E94EB
:102EE000E12D5B016C016093B8027093B90280938D
:102EF000BA029093BB02E090CB02F090CC0200911A
:102F0000CD021091CE028DB79EB783960FB6F8947E
:102F10009EBF0FBE8DBFC601B501A80197010E94DB
:102F2000872D21EE3EE245E652E40E94F12F0E94F9
:102F3000492E7093AF026093AE02C801B70120E042
:102F400030E040E850E40E94DA2D882304F56091D7
:102F5000E9027091EA02882777FD8095982F0E94F8
:102F60007C2E6093CF027093D0028093D102909315
:102F7000D202C601B50120E030E040E450E40E94F6
:102F8000DA2D882324F41092AF021092AE026091E1
:102F9000E9027091EA02882777FD8095982F0E94B8
:102FA0007C2E9B01AC016091CF027091D002809188
:102FB000D1029091D2020E94132D20E030E044EB28
:102FC00053E40E94142D20E030E044EB52E40E94D0
:102FD000142D20E030E044EB53E40E94BE2E9B0110
:102FE000AC01CA01B9010E94492ECB017093B40211
:102FF0006093B30221E06936720734F0885691403D
:103000009093B4028093B3028091AE029091AF028C
:1030100097FF04C01092AF021092AE028091AE02F0
:103020009091AF02853B910534F084EB90E0909352
:10303000AF028093AE028091B3029091B402843BC0
:10304000910594F0845B90409093B4028093B30216
:1030500084EB90E02091AE023091AF02821B930B83
:103060009093AF028093AE026091B3027091B4026C
:1030700080E00E943C096091AE027091AF0281E055
:103080000E943C0980913A02882309F443C180914F
:10309000B702882309F03EC18091A801882309F472
:1030A00039C18091B602882321F01092B6020E94A5
:1030B000B72480913A02823009F4A8C0833009F421
:1030C000E6C0813009F026C16091E9027091EA0200
:1030D000882777FD8095982F40E023E000E0EE24DC
:1030E0000E949D0F9C0180E060E040E251E00FED06
:1030F0000E941E0CE090CB02F090CC020091CD0219
:103100001091CE02C801B70120E030E040E251E466
:103110000E94DA2D882384F4C801B70120E030E052
:1031200040E251E40E94F12F0E944E2E40E023E045
:1031300001E0EE24E39408C0C801B7010E944E2EBE
:1031400040E023E000E0EE240E949D0F9C0188E017
:1031500060E045E251E00DE60E941E0C6091CF0256
:103160007091D0028091D1029091D2020E944E2E95
:1031700040E023E000E0EE240E949D0F9C0180E0EF
:1031800061E04AE251E00FED0E941E0C6091B8022E
:103190007091B9028091BA029091BB020E944E2EAA
:1031A00041E022E000E00E949D0F9C0188E061E088
:1031B0004FE251E00DE60E941E0C6091B302709147
:1031C000B402882777FD8095982F40E023E000E047
:1031D0000E949D0F9C0180E062E044E351E00FED0E
:1031E0000E941E0C6091AE027091AF02882777FD9D
:1031F0008095982F40E023E000E00E949D0F9C0105
:1032000088E062E049E351E00FED82C06091F20294
:103210007091F3028091F4029091F50240E02BE06E
:1032200007E057E0E52E0E949D0F9C0180E060E0E2
:103230004EE351E000E00E941E0C6091F602709196
:10324000F7028091F8029091F90240E02BE007E04C
:103250000E949D0F9C0180E061E044E451E000E0A9
:103260000E941E0C6091FA027091FB028091FC0298
:103270009091FD0241E02BE003E0EE24E3940E94F4
:103280009D0F9C0180E062E04AE451E040C0609103
:10329000DD027091DE028091DF029091E00240E059
:1032A0002BE007E037E0E32E0E949D0F9C0180E0B9
:1032B00060E041E551E000E00E941E0C6091E102F7
:1032C0007091E2028091E3029091E40240E02BE0F1
:1032D00007E00E949D0F9C0180E061E047E551E01E
:1032E00000E00E941E0C6091E5027091E602809160
:1032F000E7029091E80241E02BE003E0EE24E39442
:103300000E949D0F9C0180E062E04DE551E000E0ED
:103310000E941E0C0E94F10B28960FB6F894DEBF97
:103320000FBECDBFCF91DF911F910F91FF90EF9016
:10333000DF90CF90BF90AF9008958091AC0288232A
:1033400081F0F8941092AC02789480913802823027
:1033500011F40E94A61680913A02843011F40E9462
:10336000DF0808950E9480150E949D190E94270879
:1033700080913802813011F40E94600908950E9402
:10338000B21980E00E944B1180E20E9447268823F8
:1033900021F48091A801882311F41092A9010895C5
:1033A0002F923F924F925F926F927F928F929F9255
:1033B000AF92BF92CF92DF92EF92FF920F931F9343
:1033C000DF93CF93CDB7DEB727970FB6F894DEBF64
:1033D0000FBECDBF962ED72E782E692E29833A8325
:1033E0004B835C8317012801CD82BF82AE82B82C4B
:1033F0008C2D61E00E94D824692D7D2D872D962D7E
:103400002E813F81F90109951EC000D0EDB7FEB7AE
:103410001182B282692D7D2D872D962D29813A81C9
:103420004B815C8182017101CD80AA24A3948E809E
:103430009F800E94680C962ED72E782E692E0F90B2
:103440000F900E94BF1980E20E943726882321F442
:103450008091A9018823C9F60E94B724E9EAF1E026
:1034600001900020E9F73197E95AF1408E2F0E9430
:10347000A112692D7D2D872D962D27960FB6F894D4
:10348000DEBF0FBECDBFCF91DF911F910F91FF9097
:10349000EF90DF90CF90BF90AF909F908F907F90F4
:1034A0006F905F904F903F902F9008958F92AF92C2
:1034B000BF92CF92EF92FF920F931F9384E40E94EA
:1034C000D50E6091A50170E080E090E020E030E052
:1034D00040E050E0A6E0EA2EF12C012D112DF3E0A2
:1034E000CF2EE8E3AE2EECE0BE2E88240E94D01949
:1034F0009B01AC018091A50190E0A0E0B0E028170D
:1035000039074A075B07C1F02093A5018FE790E0D8
:10351000622F0E94123284E06EE10E94BF06E091A9
:10352000A501F0E0EE0FFF1FEE0FFF1FEA59FE4F5F
:10353000808191810E94952989EA91E00E94E90C9D
:103540001F910F91FF90EF90CF90BF90AF908F9011
:1035500008958F92AF92BF92CF92EF92FF920F9306
:103560001F9389E20E94D50E6091390270E080E0DD
:1035700090E020E030E040E050E0F1E0EF2EF12C70
:10358000012D112DE3E0CE2EB0E5AB2EBEE0BB2E1B
:1035900088240E94D0199B01AC018091390290E0EF
:1035A000A0E0B0E0281739074A075B0759F02093DD
:1035B00039028EE790E0622F0E94123284E06EE1C1
:1035C0000E94BF0689EA91E00E94E90C1F910F91C9
:1035D000FF90EF90CF90BF90AF908F9008958F9213
:1035E000AF92BF92CF92EF92FF920F931F938AE216
:1035F0000E94D50E6091A40170E080E090E020E090
:1036000030E040E050E0E4E6EE2EF12C012D112DEB
:10361000B7E0CB2EA6EBAA2EA0E1BA2E8824839485
:103620000E94D0199B01AC018091A40190E0A0E020
:10363000B0E0281739074A075B0759F02093A40127
:103640008DE790E0622F0E94123284E06EE10E94CA
:10365000BF0689EA91E00E94E90C1F910F91FF904B
:10366000EF90CF90BF90AF908F90089580913802E7
:10367000823039F0833041F0813041F40E94EF1AFA
:1036800008950E94A91A08950E94561A08958F92CB
:10369000AF92BF92CF92EF92FF920F931F9387E268
:1036A0000E94D50E6091380270E080E090E020E04A
:1036B00030E040E050E0B3E0EB2EF12C012D112D75
:1036C000A3E0CA2EF8E6AF2EFEE0BF2E88240E94AB
:1036D000D0199B01AC018091380290E0A0E0B0E0ED
:1036E000281739074A075B0709F440C0F894622F8E
:1036F0002093380278948CE790E00E94123284E0A4
:103700006EE10E94BF06809138020E94E92A81E0A2
:103710008093B70210923C0210923D0210923E023A
:1037200010923F0210924002109241021092420207
:10373000109243020E942E0980913802882321F4BE
:1037400020E044EF51E00BC00E9477260DC0FA0143
:103750003197F1F70197D9F72F5F223019F080EDFB
:1037600097E0F5CF0E94BE270E94170989EA91E0F1
:103770000E94E90C1F910F91FF90EF90CF90BF90A6
:10378000AF908F9008958F92AF92BF92CF92EF92A9
:10379000FF920F931F9385E10E94D50E60918701E0
:1037A00070E080E090E020E030E040E050E0A8EC05
:1037B000EA2EF12C012D112DF4E0CF2EECE2AE2EED
:1037C000E1E1BE2E882483940E94D0199B01AC01B4
:1037D0008091870190E0A0E0B0E0281739074A0700
:1037E0005B0759F02093870189E090E0622F0E94E7
:1037F000123284E06EE10E94BF0689EA91E00E94E5
:10380000E90C1F910F91FF90EF90CF90BF90AF9078
:103810008F9008958F92AF92BF92CF92EF92FF92C6
:103820000F931F9383E10E94D50E609188017091E0
:10383000890180918A0190918B0126E232E040E07B
:1038400050E0F8E7EF2EF5E0FF2E012D112DE4E01A
:10385000CE2EBCE2AB2EB1E1BB2E882483940E9415
:10386000D019AB01BC018091880190918901A09190
:103870008A01B0918B01481759076A077B0701F14C
:10388000409388015093890160938A0170938B0162
:103890008AE090E00E942032809188019091890115
:1038A000A0918A01B0918B018093C5029093C602CA
:1038B000A093C702B093C80284E06EE10E94BF06E5
:1038C00089EA91E00E94E90C1F910F91FF90EF901F
:1038D000CF90BF90AF908F9008958F92AF92BF928C
:1038E000CF92EF92FF920F931F938DE00E94D50E1F
:1038F00080E061E00E94D8248EE090E00E94450DB7
:103900000E94E6246091860170E080E090E020E073
:1039100030E040E050E0EFE1EE2EF12C012D112DD2
:10392000B6E0CB2EA9EBAA2EADE0BA2E8824839464
:103930000E94D0199B01AC018091860190E0A0E02B
:10394000B0E0281739074A075B0791F020938601FA
:1039500088E090E0622F0E94123284E06EE10E94C3
:10396000BF0680918601882319F4109236022F98A1
:1039700089EA91E00E94E90C1F910F91FF90EF906E
:10398000CF90BF90AF908F9008958F92AF92BF92DB
:10399000CF92EF92FF920F931F9388E30E94D50E70
:1039A00082E061E00E94D8248CE090E00E94450D06
:1039B0000E94E62480E091E00E94E6246091BE022D
:1039C00070E080E090E020E030E040E050E0BEE1D8
:1039D000EB2EF12C012D112DABE0CA2EF1E2AF2E12
:1039E000F1E1BF2E88240E94D0199B01AC01809187
:1039F000BE0290E0A0E0B0E0281739074A075B0755
:103A000059F02093BE0287E090E0622F0E941232AC
:103A100084E06EE10E94BF0689EA91E00E94E90C11
:103A20001F910F91FF90EF90CF90BF90AF908F902C
:103A300008958F92AF92BF92CF92DF92EF92FF9252
:103A40000F931F930E949808D82E1091AD020E94E8
:103A5000DB26BC0176956795812F0E94C4272091B3
:103A6000C00230E08091AD0290E0FC0113E0EE0F67
:103A7000FF1F1A95E1F7E81BF90BEA56FE4F658127
:103A8000768180E090E0F901EE0FFF1FE20FF31F57
:103A9000EE0FFF1FEE0FFF1FE255FE4F2085318511
:103AA00040E050E0E284F38400E010E0F5E0CF2E47
:103AB000EFE7AE2EE0E1BE2E882483940E94D01959
:103AC000AB01BC018091AD02282F30E0F90113E079
:103AD000EE0FFF1F1A95E1F7E21BF30BEA56FE4FBC
:103AE00085819681A0E0B0E0481759076A077B07F7
:103AF000B1F05683458381E390E0289FB001299F70
:103B0000700D389F700D1124665E7F4FCF0147E026
:103B100050E00E94083284E06EE10E94BF068D2DC5
:103B20000E94180D1F910F91FF90EF90DF90CF90A2
:103B3000BF90AF908F90089584E20E94D50E0E94AE
:103B4000191D089580E20E94D50E0E94191D089546
:103B50008F92AF92BF92CF92DF92EF92FF920F932C
:103B60001F930E949808D82E8091AD0260E070E00B
:103B70000E94C4272091C00230E08091AD0290E005
:103B8000FC0103E0EE0FFF1F0A95E1F7E81BF90BBC
:103B9000EA56FE4F6181728180E090E0F901EE0FFC
:103BA000FF1FE20FF31FEE0FFF1FEE0FFF1FDF01DE
:103BB000A255BE4F2D913C9140E050E0E055FE4FA4
:103BC000E080F18000E010E0E6E0CE2EB5EFAB2E15
:103BD000B0E1BB2E882483940E94D019AB01BC01B4
:103BE0008091AD02282F30E0F901A3E0EE0FFF1F16
:103BF000AA95E1F7E21BF30BEA56FE4F8181928111
:103C0000A0E0B0E0481759076A077B0741F15283EB
:103C1000418381E390E0289FB001299F700D389F78
:103C2000700D1124665E7F4FCF0147E050E00E9487
:103C300008328091AD02282F30E0F90193E0EE0FB9
:103C4000FF1F9A95E1F7E21BF30BEA56FE4F6581E1
:103C500076810E94332784E06EE10E94BF068D2D9D
:103C60000E94180D1F910F91FF90EF90DF90CF9061
:103C7000BF90AF908F90089583E20E94D50E0E946E
:103C8000A81D08958FE10E94D50E0E94A81D0895D9
:103C90008F92AF92BF92CF92DF92EF92FF920F93EB
:103CA0001F930E949808D82E1091AD020E94DB2627
:103CB000BC01812F0E94C4272091C00230E0809176
:103CC000AD0290E0FC0103E0EE0FFF1F0A95E1F763
:103CD000E81BF90BEA56FE4F6381748180E090E0A7
:103CE000F901EE0FFF1FE20FF31FEE0FFF1FEE0FA4
:103CF000FF1FDF01AE54BE4F2D913C9140E050E0DC
:103D0000E255FE4FE680F78000E010E0E6E0CE2EC0
:103D1000B3ECAB2EB0E1BB2E882483940E94D01963
:103D2000AB01BC018091AD02282F30E0F901A3E086
:103D3000EE0FFF1FAA95E1F7E21BF30BEA56FE4FC9
:103D400083819481A0E0B0E0481759076A077B0798
:103D500041F15483438381E390E0289FB001299F80
:103D6000700D389F700D1124665E7F4FCF0147E0C4
:103D700050E00E9408328091AD02282F30E0F90116
:103D800093E0EE0FFF1F9A95E1F7E21BF30BEA5663
:103D9000FE4F658176810E94332784E06EE10E94A8
:103DA000BF068D2D0E94180D1F910F91FF90EF906F
:103DB000DF90CF90BF90AF908F90089582E20E94E5
:103DC000D50E0E94481E08958EE10E94D50E0E94D5
:103DD000481E08958F92AF92BF92CF92DF92EF92DA
:103DE000FF920F931F930E949808D82E8091AD02E6
:103DF00090E0FC01B3E0EE0FFF1FBA95E1F7E81B7E
:103E0000F90BEA56FE4F608170E080E090E020E020
:103E100030E040E050E0A1E0EA2EF12C012D112D20
:103E2000F6E0CF2EEAEAAE2EEDE0BE2E88240E9408
:103E3000D0199B01AC016091AD02862F90E0FC018E
:103E400073E0EE0FFF1F7A95E1F7E81BF90BEA56D6
:103E5000FE4F808190E0A0E0B0E0281739074A07C4
:103E60005B0729F12083862F622F0E94E82620918C
:103E7000AD0230E0C90143E0880F991F4A95E1F790
:103E8000821B930B41E350E0249FB001259F700DEE
:103E9000349F700D1124665E7F4F8A569E4F47E017
:103EA00050E00E94083284E06EE10E94BF068D2D32
:103EB0000E94180D1F910F91FF90EF90DF90CF900F
:103EC000BF90AF908F90089581E20E94D50E0E941E
:103ED000EA1E08958DE10E94D50E0E94EA1E089503
:103EE0008F92AF92BF92CF92EF92FF920F931F9358
:103EF0008CE10E94D50E88E061E00E94D824609198
:103F0000C00270E080E090E020E030E040E050E06F
:103F1000A1E0EA2EF12C012D112DF5E0CF2EE2E9E2
:103F2000AE2EEDE0BE2E88240E94D0199B01AC017C
:103F30008091C00290E0A0E0B0E0281739074A075E
:103F40005B0799F0F8942093C00289E190E0622F1A
:103F50000E9412328091C0020E94D6090E947726E8
:103F6000789484E06EE10E94BF0689EA91E00E94A5
:103F7000E90C1F910F91FF90EF90CF90BF90AF9001
:103F80008F9008958F92AF92BF92CF92EF92FF924F
:103F90000F931F9380E00E94D50E60918D0170E019
:103FA00080E090E020E030E040E050E0F2E0EF2EF2
:103FB000F12C012D112DE3E0CE2EB3E7AB2EBDE0A9
:103FC000BB2E88240E94D0197B018C0180E190E0F7
:103FD0000E94F43180938D0190E0A0E0B0E0E816FB
:103FE000F9060A071B0759F0E0928D0180E190E085
:103FF0006E2D0E94123284E06EE10E94BF0689EAB3
:1040000091E00E94E90C1F910F91FF90EF90CF90EB
:10401000BF90AF908F9008958F92AF92BF92CF9242
:10402000EF92FF920F931F9386E00E94D50E60914E
:104030008C0170E080E090E021E030E040E050E072
:10404000E7E0EE2EF12C012D112DB3E0CB2EAAE5E9
:10405000AA2EAAE0BA2E88240E94D0199B01AC0196
:1040600080918C0190E0A0E0B0E0281739074A0762
:104070005B0751F48091EF0290E0A0E0B0E02817D8
:1040800039074A075B07F9F020938C012093EF0270
:104090008EE090E0622F0E94123284E06EE10E9476
:1040A000BF0680918C010E9486058091A90188231A
:1040B00051F460E00E94D82460918C0170E080E0AF
:1040C00090E00E945A0A89EA91E00E94E90C1F914F
:1040D0000F91FF90EF90CF90BF90AF908F90089589
:1040E0008F92AF92BF92CF92EF92FF920F931F9356
:1040F00085E00E94D50E6091370270E080E090E08C
:1041000020E030E040E050E0B2E0EB2EF12C012D59
:10411000112DA3E0CA2EF7E8AF2EFEE0BF2E8824B3
:104120000E94D0199B01AC018091370290E0A0E081
:10413000B0E0281739074A075B0711F1F89420937C
:1041400037028FE090E0622F0E94123284E06EE12D
:104150000E94BF06809137020E94A005982F80938D
:10416000CA028091A901882351F4809137028230DC
:1041700010F064E601C06BEF892F0E94340A789436
:1041800089EA91E00E94E90C1F910F91FF90EF9056
:10419000CF90BF90AF908F9008950F931F93CF93C0
:1041A000DF93EC01062F142F8091AA01882309F5D3
:1041B00090913802892F81508330D8F40F5F91306D
:1041C00029F4FE01E00FF11D83E480838091380221
:1041D000823031F4FE01E00FF11D89E280830F5F30
:1041E00080913802833029F4FE01E00FF11D82E353
:1041F00080830E94B72480E061E00E94D8248CEF85
:104200000E946724CE01612F402F0E941A0F2AC0FE
:1042100080E40E942126882329F480E40E942C2631
:10422000882351F0112311F4102F01C01150CE0139
:10423000612F402F0E941A0F80E80E9421268823B8
:1042400029F480E80E942C26882351F0101710F0E2
:1042500010E001C01F5FCE01612F402F0E941A0F96
:104260000E94BF1980E20E943726882321F48091A2
:10427000A901882369F60E94B7248091A9018823A7
:10428000E1F0E9EAF1E0DF010D900020E9F7119794
:10429000AE1BBF0B112369F081E08093B202EA2FBD
:1042A000F0E0E755FE4F105D108311820E94690611
:1042B00006C08A2F0E94A11202C00E947412DF91D0
:1042C000CF911F910F910895DF93CF9300D000D02D
:1042D0000F92CDB7DEB7DE011196E6ECF1E085E096
:1042E00001900D928150E1F7CE01019664E040917A
:1042F000B2020E94CD2089EA91E00E94E90C0F9061
:104300000F900F900F900F90CF91DF910895DF9352
:10431000CF9300D00F92CDB7DEB7DE011196EBEC54
:10432000F1E083E001900D928150E1F7CE0101961A
:1043300062E04091B2020E94CD2089EA91E00E94A1
:10434000E90C0F900F900F90CF91DF910895DF93BC
:10435000CF9300D00F92CDB7DEB7DE011196EEEC11
:10436000F1E083E001900D928150E1F7CE010196DA
:1043700062E04091B2020E94CD2089EA91E00E9461
:10438000E90C0F900F900F90CF91DF910895DF937C
:10439000CF9300D000D00F92CDB7DEB7DE011196DB
:1043A000E1EDF1E085E001900D928150E1F7CE0161
:1043B000019664E04091B2020E94CD2081E080939A
:1043C000AD0289EA91E00E94E90C0F900F900F90E6
:1043D0000F900F90CF91DF910895DF93CF9300D08E
:1043E00000D00F92CDB7DEB7DE011196E6EDF1E019
:1043F00085E001900D928150E1F7CE01019664E0D5
:104400004091B2020E94CD201092AD0289EA91E063
:104410000E94E90C0F900F900F900F900F90CF918A
:10442000DF910895DF93CF9300D000D0CDB7DEB7F2
:1044300084E089838CE18A838FE38B8380E48C839F
:10444000CE01019663E04091B2020E94CD2089EA3C
:1044500091E00E94E90C0F900F900F900F90CF9178
:10446000DF910895DF93CF9300D00F92CDB7DEB7E1
:10447000DE011196EEEDF1E083E001900D928150A6
:10448000E1F7CE01019662E04091B2020E94CD2098
:1044900089EA91E00E94E90C0F900F900F90CF9164
:1044A000DF910895DF93CF93CDB7DEB72B970FB68B
:1044B000F894DEBF0FBECDBFDE011196E1EEF1E054
:1044C0008BE001900D928150E1F789EA91E064E67A
:1044D00071E00E948831CE01019668E04091B202FD
:1044E0000E94CD2089EA91E00E94E90C2B960FB63C
:1044F000F894DEBF0FBECDBFCF91DF91089502C00B
:104500000E94BF1980E20E943726882321F48091FF
:10451000A9018823A9F70E94B7248091A9018823C3
:1045200019F40E94741203C081E00E946906809110
:10453000A901811181E0089581E30E94D50E80E0F8
:1045400061E00E94D8248BE390E00E94450D0E9418
:10455000E62480E062E00E94D8248CE390E00E9490
:10456000450D0E94E6240E94DF0884E080933A0211
:104570008093B2020E947F22882339F0E9EAF1E0B9
:1045800001900020E9F73297108210923A0289EAEE
:1045900091E00E94E90C0895CF93DF93E9EAF1E0FE
:1045A00001900020E9F73197E95AF140E150CE2F10
:1045B000D0E0C755DE4F8881805380933A028093C4
:1045C000B20281E08093B60280E390E00E94450D44
:1045D0000E94E6240E947F228111188210923A02E2
:1045E00089EA91E00E94E90CDF91CF9108950F9341
:1045F0001F93DF93CF93CDB7DEB764970FB6F894D0
:10460000DEBF0FBECDBF86E30E94D50E88E090E0EE
:104610000E94450DBC018E010F5F1F4FC8010E9413
:1046200088318AE090E00E94450DBC01C8010E94DB
:104630007431C80161E00E949A0A8BE090E00E9408
:10464000450D62E00E949A0A0E947F22882359F059
:104650008091A6019091A7010E9431131092A901A7
:104660000E94741204C089EA91E00E94E90C6496E9
:104670000FB6F894DEBF0FBECDBFCF91DF911F9173
:104680000F9108950F931F93DF93CF93CDB7DEB7AC
:1046900064970FB6F894DEBF0FBECDBF85E30E94CE
:1046A000D50E88E090E00E94450DBC018E010F5FA1
:1046B0001F4FC8010E94883189E090E00E94450D9B
:1046C000BC01C8010E947431C80161E00E949A0ACD
:1046D0008BE090E00E94450D62E00E949A0A0E94E1
:1046E0007F22882359F08091A6019091A7010E9412
:1046F00067131092A9010E94741204C089EA91E024
:104700000E94E90C64960FB6F894DEBF0FBECDBFD1
:10471000CF91DF911F910F9108958F929F92AF9249
:10472000CF92DF92EF92FF920F931F9388EE93E068
:1047300024EF31E0F9013197F1F70197D9F7239A86
:104740002B9887B18F7387B9579886B190E0807C9A
:1047500009F091E0892F0E949D134F9904C036996A
:1047600002C00E94FC0881B18F6181B984B1876168
:1047700084B980918C010E94860580918C01809380
:10478000EF0213980E94FF0585E085BD80916E00C1
:10479000816080936E0083E08093B100809170000F
:1047A0008160809370008AB1837F8AB980916900AB
:1047B0008A6080936900809137020E94A0058AB1C7
:1047C00080638AB980913802882311F00E9477268D
:1047D0008091F0026091BE0240E020E00E94082536
:1047E0000E94BE058DE99AE066E00E949A240E942C
:1047F000A60E82E06EE10E94BF06789480918D0142
:104800008E3F21F410928D010E94C21F1092A901C7
:104810000E947412DD24D3940E94B2120E94DC0B19
:104820000E94B2198091A8018823B1F380E20E940E
:104830003726882321F0D092B2020E94522200D063
:1048400060918C0170E080E090E0EDB7FEB7D1821E
:10485000128221E030E040E050E0F7E0EF2EF12C52
:10486000012D112DCC24AA24EAE58E2EEAE09E2EFD
:104870000E94680C0F900F9080918C01681761F274
:1048800060938C01862F0E948605C6CF28B1982F91
:104890009F70922B98B998B1806F982398B9459AD8
:1048A0008DE08A95F1F7459888EC8A95F1F708959F
:1048B0001F93182F82958F700E944624812F0E948B
:1048C00046241F91089544980E9458240895449ABC
:1048D0000E9458240895EF92FF920F931F93CF9355
:1048E000DF93182F7B0188E20E946324012F10E0E0
:1048F00083E0000F111F8A95E1F7C0E0D0E09E0130
:10490000200F822F80640E946324F701EC0FFD1FAB
:10491000E4918E2F0E9467242196C830D10579F743
:1049200089E20E946324DF91CF911F910F91FF9044
:10493000EF900895EF92FF920F931F93CF93DF9321
:104940007C01062F10E0C0E0D0E008C0B7016C0F7A
:104950007D1F812F0E946B241F5F28961017B0F3D4
:10496000DF91CF911F910F91FF90EF90089581E01B
:104970000E94632480E197E20197F1F708950F9375
:104980001F93162F813011F400E501C004E589E280
:104990000E946324812F8F7080670E946324129588
:1049A0001370802F812B0E9463241F910F91089513
:1049B000813108F080E0643008F060E06295607F4B
:1049C000680F862F80680E94632408950F931F93B9
:1049D000CF93DF93EC0100E010E00FC08A3051F478
:1049E000133010F010E001C01F5F80E0612F0E94C3
:1049F000D82402C00E9467240F5FFE01E00FF11D62
:104A00008081882359F7DF91CF911F910F910895ED
:104A1000CF92DF92EF92FF920F931F93582F162F92
:104A2000C42E022F279A3D9A3C9A87B18F6087B98E
:104A3000459880E991E024EF31E0F9013197F1F7F1
:104A40000197D9F7513039F4EDE1FE2E7CE6D72EEF
:104A500060E5E62E06C055E1F52E4EE6D42E34E58F
:104A6000E32E449883E00E94462480E197E2019778
:104A7000F1F783E30E94462482E30E94632489E2E3
:104A80000E9463248F2D0E946324812F8F70806782
:104A90000E946324129513708E2D812B0E94632433
:104AA0008D2D0E94632488E20E94632401700C60B3
:104AB0008C2D90E081709070880F991F802B0E9440
:104AC00063240E94B72486E00E9463241F910F9103
:104AD000FF90EF90DF90CF9008951F920F920FB646
:104AE0000F9211242F933F938F939F938DE386BD55
:104AF00026B189B13091880390E0807890709595C7
:104B0000879595958795207C282B20952327809144
:104B10009002822380958093900290918F0292233D
:104B2000982790938F028223892390918803982756
:104B3000909388032091ED02909188038923822B22
:104B40008093ED028091ED02807E51F01092BD02C3
:104B50001092BC0288EE93E0909321028093200291
:104B600080918803807E49F482E380938E0284E101
:104B70008093C30286E08093B10280918E028150BF
:104B800080938E02882361F48091C30280938E0209
:104B90009091C10280918803807E892B8093C1020D
:104BA00080918D02815080938D02882331F482E3BD
:104BB00080938D0281E08093EB0280918C02815082
:104BC00080938C02882331F484E180938C0281E00D
:104BD0008093BF0280918B02815080938B02882347
:104BE00031F482E080938B0281E08093C90280914E
:104BF0008A02815080938A02882331F48AE080936C
:104C00008A0281E08093AC0280912002909121027F
:104C100001979093210280932002892B49F488EE1A
:104C200093E0909321028093200281E08093870398
:104C30009F918F913F912F910F900FBE0F901F90DA
:104C40001895F8949091ED0289239091ED029827A0
:104C50009093ED0278940895F8949091C10289237D
:104C60009091C10298279093C10278940895F89486
:104C700090918803F8942091ED02909589238223E6
:104C80009091ED0298279093ED0278940895982FD3
:104C9000F8948091C10298238091C1028927809362
:104CA000C1027894F8948091ED0289239091ED02ED
:104CB00098279093ED02789408958823B9F0809115
:104CC000B102882341F0F8948091B1028150809321
:104CD000B102789408958091C302843038F0F8943A
:104CE0008091C30282508093C3027894089580918A
:104CF0006F008D7F80936F00E091C002EE2309F07A
:104D000051C0809181008C7F8093810080918100CF
:104D100084608093810080E18093890380E28093A6
:104D200095031092A2031092A103F0E083E0EE0F2E
:104D3000FF1F8A95E1F7EE5DFD4F2681378140E048
:104D400050E060E07DE281E391E00E94F030CA0132
:104D5000B90124E130E040E050E00E94B1300E940F
:104D60007A2E2FE632E143E85AE30E94F12F0E94A7
:104D70004E2EAB017093A4036093A303309188007F
:104D800020918900922F80E0830F911D840F951F41
:104D9000909389008093880080916F008260809357
:104DA0006F000895809181008B7F809381008091B6
:104DB00081008360AECFE091C002F0E093E0EE0F9F
:104DC000FF1F9A95E1F7EA5DFD4F8081918108957B
:104DD00090E0FC01EE0FFF1FE80FF91FEE0FFF1F21
:104DE000EE0FFF1FE757FC4F61706383089590E05B
:104DF000DC01AA0FBB1FA80FB91FAA0FBB1FAA0F68
:104E0000BB1FA357BC4FE091C002F0E043E0EE0FA0
:104E1000FF1F4A95E1F7EC5DFD4F80819181860F80
:104E2000971F8D939C93089590E0DC01AA0FBB1F00
:104E3000A80FB91FAA0FBB1FAA0FBB1FA757BC4FB4
:104E4000E091C002F0E083E0EE0FFF1F8A95E1F7EA
:104E5000EE5DFD4F80819181861B970B17969C9389
:104E60008E93169708954F925F926F927F928F92D2
:104E70009F92AF92BF92CF92DF92EF92FF920F93E9
:104E80001F937B0190E0E9E8F3E09C01220F331FC0
:104E9000280F391F4901880C991C880C991C8E0E0B
:104EA0009F1ED4011B96FC92EE921A972F5F3F4FE4
:104EB000220F331F220F331FE20FF31FA080B18098
:104EC00016966D917C9117976A197B0980E090E0A6
:104ED0000E947A2E20E030E040E05FE30E94F12F54
:104EE0002B013C0100E010E0C801B7010E947A2EBE
:104EF0007B018C01E091C002F0E033E0EE0FFF1F78
:104F00003A95E1F7EA5DFD4F6081718180E090E0C4
:104F10000E947A2E20E030E040E05FEB0E94F12F0B
:104F20009B01AC01C801B7010E94142D9B01AC018B
:104F3000C301B2010E94142D7B018C01CC24DD241D
:104F4000C601B5010E947A2E9B01AC01C801B701D0
:104F50000E94142D0E944E2EF401718760871F91CC
:104F60000F91FF90EF90DF90CF90BF90AF909F9008
:104F70008F907F906F905F904F900895EFE6F0E0F4
:104F800080818D7F808308952F923F924F925F9210
:104F90006F927F928F929F92AF92BF92CF92DF9249
:104FA000EF92FF920F931F93DF93CF9300D000D027
:104FB00000D0CDB7DEB7282F30E03E832D83F90136
:104FC000EE0FFF1FE20FF31FEE0FFF1FEE0FFF1F8D
:104FD000E757FC4F8381882381F0E091C002F0E025
:104FE000B3E0EE0FFF1FBA95E1F7EA5DFD4F808158
:104FF0009181AC01461B570BBA01E091C002F0E071
:10500000A3E0EE0FFF1FAA95E1F7EA5DFD4F808157
:105010009181CD80DE80CC0CDD1C1B014424552405
:105020009C0140E050E029833A834B835C83969552
:1050300087956817790708F047C00D811E810C0D10
:105040001D1D000F111F000F111FF801E357FC4F2A
:10505000A080B180220C331C441C551CC201B1013C
:105060000E947A2E3B014C0107571C4FF8016085C6
:1050700071856A197B0980E090E00E947A2E9B017D
:10508000AC01C401B3010E94F12F7B018C01698145
:105090007A818B819C810E947A2E9B01AC01C80190
:1050A000B7010E94E12D7B018C01CC24DD24C601D7
:1050B000B5010E947A2E9B01AC01C801B7010E9484
:1050C000142D0E944E2E48C069817A818B819C816B
:1050D0000E947A2E4B015C012D813E81C20ED31EAF
:1050E000CC0CDD1CCC0CDD1C49E853E0C40ED51EF5
:1050F000F60160847184C201B1010E947A2E7B01A5
:105100008C01C501B40120E030E040E05FEB0E947B
:10511000F12F9B01AC01C801B7010E94142D9B0126
:10512000AC010E94142D7B018C01F6016681778110
:105130006619770980E090E00E947A2E9B01AC010D
:10514000C801B7010E94F12FA50194010E94E12D31
:105150000E944E2E660D771DED81FE81EE0FFF1F22
:105160002D813E81E20FF31FEE0FFF1FEE0FFF1F99
:10517000E357FC4F0190F081E02D6E177F0708F494
:10518000BF01ED81FE81EE0FFF1F4D815E81E40FB7
:10519000F51FEE0FFF1FEE0FFF1FE757FC4F868135
:1051A00097818617970708F4BC017283618326965E
:1051B0000FB6F894DEBF0FBECDBFCF91DF911F9128
:1051C0000F91FF90EF90DF90CF90BF90AF909F90A6
:1051D0008F907F906F905F904F903F902F900895A9
:1051E000482F50E0FA01EE0FFF1FE40FF51FEE0FFE
:1051F000FF1FEE0FFF1FE357FC4F0190F081E02DE2
:10520000CB016E177F0708F4CF01FA01EE0FFF1FE5
:10521000E40FF51FEE0FFF1FEE0FFF1FE757FC4FC8
:10522000268137812817390708F4C90192838183C1
:1052300008951F920F920FB60F9211242F933F9350
:105240004F935F938F939F93EF93FF9330919102CE
:10525000323090F42BB1832F90E0FC01EE0FFF1F52
:10526000E80FF91FEE0FFF1FEE0FFF1FE757FC4F70
:105270008081809582238BB9832F8F5F80939102E9
:105280008230C9F0833010F0109291022BB18091DE
:10529000910290E0FC01EE0FFF1FE80FF91FEE0FE7
:1052A000FF1FEE0FFF1FE757FC4F8081282B2BB904
:1052B000418152810AC04091A3035091A40380917F
:1052C000A1039091A203481B590B309188002091B3
:1052D0008900922F80E0830F911D840F951F90937A
:1052E0008900809388008091A1039091A203840F8C
:1052F000951F9093A2038093A1032091A303309163
:10530000A4038217930720F01092A2031092A10326
:10531000FF91EF919F918F915F914F913F912F91CD
:105320000F900FBE0F901F9018959C0140E050E029
:1053300084E0220F331F441F551F8A95D1F760E088
:105340007DE281E391E00E94F030215030403093C3
:10535000C5002093C40088E98093C10086E0809353
:10536000C2000895982F8091C00085FFFCCF9093D4
:10537000C6000895FC0107C08091C00085FFFCCFE6
:105380009093C600319690819923B1F708951F92AA
:105390000F920FB60F9211242F938F939F93EF9339
:1053A000FF932091C60080919202882309F052C099
:1053B00080913C04281771F480913502882351F0C4
:1053C0001092350285EA93E0909334028093330281
:1053D00010923D04809135028823E1F5E09133027B
:1053E000F0913402208380913D048F5F80933D04CF
:1053F00080913B04882319F02D3001F51AC080916B
:105400003D04823029F4213019F081E08093350287
:1054100080913D04833021F4223010F086E001C0F9
:1054200085E08093320290913D048091320298177A
:1054300029F481E080933502809392023196F093B3
:105440003402E093330280913D04863919F481E0FF
:1054500080933502FF91EF919F918F912F910F9043
:105460000FBE0F901F901895CF93DF93EC0130E0A3
:1054700044C04F5FE42FF0E0EB55FC4F20812D53EB
:105480004F5FE42FF0E0EB55FC4F70814F5FE42F4E
:10549000F0E04350EB55FC4F5081DE01A30FB11DEE
:1054A000922F92959F70E42FF0E0EB55FC4F808196
:1054B0008D53880F880F892B8C93613009F1972FBA
:1054C0009D533F5FFE01E30FF11D31502295207F78
:1054D000892F86958695282B2083623089F04C5F32
:1054E00063503E5FFE01E30FF11D9295990F990FF6
:1054F000907C5D53952B90833F5F662309F0B9CF75
:10550000DF91CF910895982F80919202813009F018
:105510004BC080913D04882309F446C08091A703C5
:10552000891709F041C040E050E020E006C0EB558B
:10553000FC4F8081480F511D2F5FE22FF0E08091DA
:105540003D0490E00397E817F9078CF3CA019F70B8
:10555000E0913D0426E0959587952A95E1F7835CD7
:10556000F0E0EE55FC4F20818217B1F4E0913D044C
:105570004F735070942F935CF0E0ED55FC4F808199
:10558000981751F460913D04665081EF92E043E03A
:105590000E94342A21E001C020E0F8941092D40245
:1055A0001092D302789401C020E08091D3029091B0
:1055B000D4028C5E944048F48091A703813428F093
:1055C0008B3518F481E08093B50210929202822FFD
:1055D000089590E0823009F491E090933B04992380
:1055E00011F083E201C080E880933C040895AC018F
:1055F00080913D04825080933D04809192028130DD
:1056000091F420E009C0FA01E20FF11DB0E0AB55C2
:10561000BC4F8C9180832F5FA22FA60F80913D04F9
:10562000281788F302C010923D04109292028091D4
:105630003D040895A0E3B0E0E0E2FBE20C942D31DC
:10564000A8E04E010894811C911CF401BA2F11921C
:10565000BA95E9F729833A834B835C836D837E8314
:105660008F839887CE010996FC011192AA95E9F7DC
:10567000A986BA86CB86DC86ED86FE860F87188BD8
:1056800029813A814B815C812DA73EA74FA758AB5A
:1056900079018A018FEF9FEFA0E0B0E0E822F922C4
:1056A0000A231B231A014424552429853A854B8556
:1056B0005C8529A73AA74BA75CA759016A01A822D4
:1056C000B922CA22DB223A0188249924C601B501F5
:1056D000A80197010E94B1306DA37EA38FA398A764
:1056E000C401B3010E94B13069A37AA38BA39CA328
:1056F000C601B501A20191010E94B1307B018C016C
:10570000C401B3010E94B1305B016C0189A19AA16F
:10571000ABA1BCA18E0D9F1DA01FB11F89A39AA391
:10572000ABA3BCA32DA13EA14FA158A5CA01AA2796
:10573000BB2729A13AA14BA15CA1280F391F4A1F01
:105740005B1F29A33AA34BA35CA32E153F0540077B
:10575000510740F480E090E0A1E0B0E0A80EB91E4F
:10576000CA1EDB1E89A19AA1ABA1BCA19D01442741
:1057700055272A0D3B1D4C1D5D1D2D8F3E8F4F8FD4
:1057800058A36C01BB24AA248DA19EA1AFA1B8A5EA
:10579000A070B070A80EB91ECA1EDB1EA98EBA8EEC
:1057A000CB8EDC8E9A8C8B8C7C8C9E8D6F8D78A1B1
:1057B000FE01719688E0DF011D928A95E9F72D8B35
:1057C0009E8B6F8B788F2D853E854F8558896DA573
:1057D0007EA58FA598A90E94B1307B018C012D81F7
:1057E0003E814F81588569A57AA58BA59CA50E940D
:1057F000B130E60EF71E081F191F6D897E898F894B
:10580000988D6E0D7F1D801F911F6D8B7E8B8F8BF2
:10581000988FEE892A2D392D482D572D7E2F8F896F
:10582000988DE096E2E10C944931EF92FF920F934C
:10583000DF93CF93CDB7DEB760970FB6F894DEBF96
:105840000FBECDBFA82F002309F461C07E010894CC
:10585000E11CF11C88E0F70111928A95E9F7298390
:105860003A834B835C836D837E83AF83988780E22A
:10587000801BE82FFF27E7FDF0954D815E816F814A
:105880007885181684F01D861E861F86188A88273C
:1058900099278E1B9F0B04C0769567955795479562
:1058A0008A95D2F728C0202F332727FD3095DB01BA
:1058B000CA01022E04C0B695A795979587950A94BC
:1058C000D2F78D879E87AF87B88B04C0440F551FD2
:1058D000661F771FEA95D2F789819A81AB81BC81D7
:1058E00004C0B695A795979587952A95D2F7482B2A
:1058F000592B6A2B7B2B49875A876B877C87298595
:105900003A854B855C856D857E85AF8598898A2F24
:1059100060960FB6F894DEBF0FBECDBFCF91DF917A
:105920000F91FF90EF900895EF92FF920F93DF9306
:10593000CF93CDB7DEB760970FB6F894DEBF0FBE3A
:10594000CDBFA82F002309F461C07E010894E11C9B
:10595000F11C88E0F70111928A95E9F729833A83CF
:105960004B835C836D837E83AF83988780E2801B4B
:10597000E82FFF27E7FDF09549815A816B817C81F3
:10598000181684F019861A861B861C868827992784
:105990008E1B9F0B04C0440F551F661F771F8A95EF
:1059A000D2F728C0202F332727FD3095DB01CA010D
:1059B000022E04C0880F991FAA1FBB1F0A94D2F79A
:1059C00089879A87AB87BC8704C07695679557957A
:1059D0004795EA95D2F78D819E81AF81B88504C045
:1059E000880F991FAA1FBB1F2A95D2F7482B592B46
:1059F0006A2B7B2B4D875E876F87788B29853A854D
:105A00004B855C856D857E85AF8598898A2F6096EC
:105A10000FB6F894DEBF0FBECDBFCF91DF910F91CF
:105A2000FF90EF9008955058BB27AA270ED083C24D
:105A30004CD230F051D220F031F49F3F11F41EF4DB
:105A40001CC20EF4E095E7FB04C2E92F96D280F366
:105A5000BA17620773078407950718F071F49EF56B
:105A6000AEC20EF4E0950B2EBA2FA02D0B01B9019A
:105A700090010C01CA01A0011124FF27591B99F0C4
:105A8000593F50F4503E68F11A16F040A22F232FD0
:105A9000342F4427585FF3CF469537952795A79520
:105AA000F0405395C9F77EF41F16BA0B620B730BC7
:105AB000840BBAF09150A1F0FF0FBB1F661F771F38
:105AC000881FC2F70EC0BA0F621F731F841F48F4ED
:105AD000879577956795B795F7959E3F08F0B3CF73
:105AE0009395880F08F09927EE0F9795879508955D
:105AF000ECD158F080E891E009F49EEFEDD128F068
:105B000040E851E059F45EEF09C0B7C158C2E92F2F
:105B1000E07833D268F3092E052AC1F32617370738
:105B20004807590738F00E2E07F8E02569F0E02500
:105B3000E0640AC0EF6307F8009407FADB01B901DB
:105B40009D01DC01CA01AD01EF934AD0F4D10AD026
:105B50005F91552331F02BED3FE049E450FD49ECD6
:105B600063CF0895DF93DD27B92FBF7740E85FE368
:105B70001616170648075B0710F4D92F2BD29F93F0
:105B80008F937F936F93D2D2E0E7F0E079D1D3D1B6
:105B90002F913F914F915F9130D2DD2349F0905882
:105BA000A2EA2AED3FE049EC5FE3D0785D274DDFC4
:105BB000DF91C1C12AD108F481E0089595D1E39520
:105BC000CBC10CD0B8C188D140F07FD130F021F4E6
:105BD0005F3F19F03EC15111F3C14FC1CED198F3CF
:105BE0009923C9F35523B1F3951B550BBB27AA275E
:105BF00062177307840738F09F5F5F4F220F331FD0
:105C0000441FAA1FA9F333D00E2E3AF0E0E830D09B
:105C100091505040E695001CCAF729D0FE2F27D09E
:105C2000660F771F881FBB1F261737074807AB076C
:105C3000B0E809F0BB0B802DBF01FF2793585F4FE1
:105C40002AF09E3F510568F004C1BAC15F3FECF3F2
:105C5000983EDCF3869577956795B795F7959F5FA6
:105C6000C9F7880F911D9695879597F90895E1E0FA
:105C7000660F771F881FBB1F621773078407BA0759
:105C800020F0621B730B840BBA0BEE1F88F7E095B4
:105C9000089504D06894B11193C1089576D188F025
:105CA0009F5790F0B92F9927B751A0F0D1F0660F08
:105CB000771F881F991F1AF0BA95C9F712C0B13023
:105CC00081F07DD1B1E008957AC1672F782F8827C0
:105CD000B85F39F0B93FCCF3869577956795B39562
:105CE000D9F73EF490958095709561957F4F8F4FD1
:105CF0009F4F0895E89409C097FB3EF490958095D6
:105D0000709561957F4F8F4F9F4F9923A9F0F92F81
:105D100096E9BB279395F695879577956795B795FF
:105D2000F111F8CFFAF4BB0F11F460FF1BC06F5FE5
:105D30007F4F8F4F9F4F16C0882311F096E911C0F7
:105D4000772321F09EE8872F762F05C0662371F018
:105D500096E8862F70E060E02AF09A95660F771F2C
:105D6000881FDAF7880F9695879597F90895ADD033
:105D700018F011F0B1D038F480C022C1E92FFDD065
:105D8000B0F35523C9F3E7FB621773078407950740
:105D9000A8F199F3E92FFF2788232AF03197660F9E
:105DA000771F881FDAF7952F5527442332F091503B
:105DB0005040220F331F441FD2F7BB27E91BF50BBE
:105DC000621B730B840BB109C1F222F4620F731FC3
:105DD000841FB11D31972AF0660F771F881FBB1FE4
:105DE000EFCF915050405AF041F0882332F0660FC7
:105DF000771F881F91505040C1F7939530C086950A
:105E0000779567959F5FD9F7F8CF990F0008550FE1
:105E1000AA0BE0E8FEEF16161706E807F907C0F030
:105E200012161306E407F50798F0621B730B840B38
:105E3000950B39F40A2661F0232B242B252B21F412
:105E400008950A2609F4A140A6958FEF811D811DB2
:105E5000089597F99F6780E870E060E008959F3F9C
:105E600031F0915020F4879577956795B795880F15
:105E7000911D9695879597F908959FEF80EC089569
:105E8000DF93CF931F930F93FF92EF92DF927B01EB
:105E90008C01689405C0DA2EEF01AFD0FE01E894C2
:105EA000A5912591359145915591AEF3EF01CDDD49
:105EB000FE019701A801DA9479F7DF90EF90FF9047
:105EC0000F911F91CF91DF91089500240A94161627
:105ED000170618060906089500240A9412161306D8
:105EE000140605060895C9CF50D0E8F3E894E0E021
:105EF000BB279F57F0F02AED3FE049EC06C0EE0FBC
:105F0000BB0F661F771F881F28F0B23A620773071E
:105F1000840728F0B25A620B730B840BE3959A95B1
:105F200072F7803830F49A95BB0F661F771F881F71
:105F3000D2F7904896CF092E0394000C11F48823D1
:105F400052F0BB0F40F4BF2B11F460FF04C06F5F31
:105F50007F4F8F4F9F4F0895EF93E0FF06C0A2EA57
:105F60002AED3FE049EC5FEB70DDE5DF0F90039435
:105F700001FC9058EDE9F0E0E3C057FD9058440F64
:105F8000551F59F05F3F71F04795880F97FB991F98
:105F900061F09F3F79F08795089512161306140655
:105FA000551FF2CF4695F1DF08C0161617061806E2
:105FB000991FF1CF86957105610508940895E894BD
:105FC000BB2766277727CB0197F908951EDF08F4D2
:105FD0008FEF08959B01AC0160E070E080E89FE3E3
:105FE000F0CD0BD0A8CF71DF28F076DF18F0952325
:105FF00009F02FCF42CF1124E3CFBFDFA0F3959F4D
:10600000D1F3950F50E0551F629FF001729FBB279F
:10601000F00DB11D639FAA27F00DB11DAA1F649F4B
:106020006627B00DA11D661F829F2227B00DA11DFE
:10603000621F739FB00DA11D621F839FA00D611D84
:10604000221F749F3327A00D611D231F849F600DA5
:10605000211D822F762F6A2F11249F5750408AF0DE
:10606000E1F088234AF0EE0FFF1FBB1F661F771F6A
:10607000881F91505040A9F79E3F510570F0E9CE1E
:106080009FCF5F3FECF3983EDCF38695779567955D
:10609000B795F795E7959F5FC1F7FE2B880F911D88
:1060A0009695879597F9089511F40EF4E6CED7CE1C
:1060B0006CDFD0F39923D9F3CEF39F57550B87FFAD
:1060C00038D00024A0E640EA900180585695979574
:1060D00028F4805C660F771F881F20F0261737078B
:1060E000480730F4621B730B840B202931294A2B9B
:1060F000A69517940794202531254A2758F7660F4F
:10610000771F881F20F026173707480730F4620BE7
:10611000730B840B200D311D411DA09581F7B90132
:10612000842F9158880F9695879508959B01AC010F
:1061300058CF91505040660F771F881FD2F70895AF
:106140009F938F937F936F93FF93EF939B01AC018A
:1061500048DFEF91FF9194DE2F913F914F915F9136
:1061600040CF629FD001739FF001829FE00DF11D2F
:10617000649FE00DF11D929FF00D839FF00D749FC1
:10618000F00D659FF00D9927729FB00DE11DF91F6D
:10619000639FB00DE11DF91FBD01CF0111240895CA
:1061A000991B79E004C0991F961708F0961B881F69
:1061B0007A95C9F780950895AA1BBB1B51E107C0CA
:1061C000AA1FBB1FA617B70710F0A61BB70B881F87
:1061D000991F5A95A9F780959095BC01CD01089516
:1061E000A1E21A2EAA1BBB1BFD010DC0AA1FBB1FDB
:1061F000EE1FFF1FA217B307E407F50720F0A21B4D
:10620000B30BE40BF50B661F771F881F991F1A94B9
:1062100069F760957095809590959B01AC01BD01E3
:10622000CF01089597FB092E05260ED057FD04D007
:10623000D7DF0AD0001C38F4509540953095219551
:106240003F4F4F4F5F4F0895F6F7909580957095AB
:1062500061957F4F8F4F9F4F08952F923F924F929E
:106260005F926F927F928F929F92AF92BF92CF92E6
:10627000DF92EF92FF920F931F93CF93DF93CDB7EF
:10628000DEB7CA1BDB0B0FB6F894DEBF0FBECDBF67
:1062900009942A88398848885F846E847D848C8438
:1062A0009B84AA84B984C884DF80EE80FD800C8141
:1062B0001B81AA81B981CE0FD11D0FB6F894DEBF24
:1062C0000FBECDBFED010895FB01DC018D9105905E
:1062D00080190110D9F3990B0895FB01DC01059099
:1062E0000D920020E1F70895FB01DC010D900020E4
:1062F000E9F7119701900D920020E1F70895FB0155
:10630000DC018D91019080190110D9F3990B08954A
:10631000FB01DC0101900D920020E1F70895FB01E3
:106320009F01E8944230C4F04532B4F44A3029F475
:1063300097FB1EF4909581959F4F642F77270E94BD
:10634000DC30805D8A330CF0895D8193CB0100974E
:10635000A1F716F45DE251931082C9010C942D321D
:10636000FA01CF93FF93EF93223044F1253234F5B5
:10637000C22FE894CA3049F497FB3EF4909580957B
:10638000709561957F4F8F4F9F4F2C2F3327442758
:106390005527FF93EF930E94F030EF91FF91605DDE
:1063A0006A330CF0695D6193B901CA0160507040B5
:1063B0008040904051F716F4CDE2C19310828F9146
:1063C0009F91CF910C942D32DC01CB01FC01F99906
:1063D000FECF06C0F2BDE1BDF89A319600B40D9231
:1063E00041505040B8F70895F999FECF92BD81BD54
:1063F000F89A992780B50895A6E1B0E044E050E00E
:106400000C94E631A8E1B0E042E050E00C94E631B3
:10641000DC01CB0103C02D910E941332415050404A
:10642000D0F70895262FF999FECF1FBA92BD81BDEE
:1064300020BD0FB6F894FA9AF99A0FBE0196089506
:10644000242F0E941332252F0E9413320C942832DD
:106450000E941232272F0C941332DC01FC01672FAB
:1064600071917723E1F7329704C07C916D9370832B
:0E6470006291AE17BF07C8F30895F894FFCFEE
:10647E003A20004D487A002A2000560A310A32008E
:10648E00312E31300023636F3F5D3D3D45480D0099
:10649E004469723A004469733A004265613A0041B8
:1064AE006C743A0050616E3A0054696C3A00614C5B
:1064BE006F6E3A00614C61743A0061416C743A201F
:1064CE0000684C6F6E3A00684C61743A0068416C1B
:1064DE00743A20003000C0120000201C00008025FD
:1064EE00000040380000004B00000096000000E164
:1064FE000000000000001F55C003000001FECC018B
:10650E004B0080008000002D002D007F00002D002C
:10651E002D007F00280593020130000000000000CE
:10652E006400000064006600980000009001000006
:10653E0090019B016302042D2E2F31041415040CBF
:10654E000D0421222324041D1E1F200102030435E5
:10655E003604050607001B381227002C393A37354A
:10656E00373430003537363000353738300035386F
:10657E00303000353832300035383430003538366A
:10658E003000EF01F401F901FE01030208020D02D1
:10659E00E803D3001A00FF0000014C036800FF035C
:0665AE00400006A50301F8
:040000050080043C37
:00000001FF
/NGVideo5_8/tags/v1.11/Hexfiles
Property changes:
Added: bugtraq:number
+true
\ No newline at end of property
/NGVideo5_8/tags/v1.11/KurzanleitungFW.pdf
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/NGVideo5_8/tags/v1.11/NGVideo_5_8GHz.pnproj
0,0 → 1,0
<Project name="NGVideo_5_8GHz"><File path="makefile"></File><File path="main.c"></File><File path="dogm.c"></File><File path="dogm.h"></File><File path="config.h"></File><File path="keys.c"></File><File path="servo.c"></File><File path="servo.h"></File><File path="ngvideo.h"></File><File path="keys.h"></File><File path="usart.c"></File><File path="usart.h"></File><File path="tracking.c"></File><File path="ngvideo.c"></File><File path="menue.c"></File><File path="messages.c"></File><File path="messages.h"></File><File path="menue.h"></File></Project>
/NGVideo5_8/tags/v1.11/NGVideo_5_8GHz.pnps
0,0 → 1,0
<pd><ViewState><e p="NGVideo_5_8GHz" x="true"></e></ViewState></pd>
/NGVideo5_8/tags/v1.11/config.h
0,0 → 1,149
/****************************************************************/
/* */
/* NG-Video 5,8GHz */
/* */
/* Copyright (C) 2011 - gebad */
/* */
/* This code is distributed under the GNU Public License */
/* which can be found at http://www.gnu.org/licenses/gpl.txt */
/* */
/****************************************************************/
 
#ifndef CONFIG_H_
#define CONFIG_H_
 
/* PINA */
#define VBAT 7 // ADC
#define RSSI1 6 // ADC
#define RSSI0 5 // ADC
#define MUX_IN 4 // OUT
#define MUX_EN 3 // OUT
#define CHANNel_12 2 // OUT
#define CHANNel_11 1 // OUT
#define CHANNel_10 0 // OUT
 
/* PINB */
#define LCD_BACKLIGHT 7 // OUT
#define BEEPER 4 // OUT
#define POWER 3 // OUT
#define CHANNel_02 2 // OUT
#define CHANNel_01 1 // OUT
#define CHANNel_00 0 // OUT
 
/* PINC */
#define KEY_MINUS 7 // IN
#define KEY_PLUS 6 // IN
#define LCD_ENABLE 5 // OUT
#define LCD_REGSELECT 4 // OUT
#define LCD_DATA7 3 // OUT
#define LCD_DATA6 2 // OUT
#define LCD_DATA5 1 // OUT
#define LCD_DATA4 0 // OUT
 
/* PIND */
#define KEY_ENTER 7 // IN
#define HSYNC 6 // IN
#define SERVO1 5 // OUT PWM
#define SERVO2 4 // OUT PWM
#define VSYNC1 3 // IN Int1
#define VSYNC0 2 // IN Int0
#define TX 1 // OUT USART
#define RX 0 // IN USART
/* PORT - DDR */
/* LCD */
#define LCD_BACKLIGHT_PORT PORTB
#define LCD_BACKLIGHT_DDR DDRB
#define LCD_E_PORT PORTC
#define LCD_E_DDR DDRC
#define LCD_RS_PORT PORTC
#define LCD_RS_DDR DDRC
#define LCD_DATA_PORT PORTC
#define LCD_DATA_DDR DDRC
#define LCD_DATA_PIN PINC
 
#define LCD_LINES 3
#define LCD_COLS 16
 
/* SWITCH */
#define KEY_MP_DDR DDRC
#define KEY_MP_PORT PORTC
#define KEY_MP_PIN PINC
#define KEY_ENTER_DDR DDRD
#define KEY_ENTER_PORT PORTD
#define KEY_ENTER_PIN PIND
 
#define SW_MINUS 7
#define SW_PLUS 6
#define SW_ENTER 5
#define REPEAT_MASK (1<<SW_MINUS | 1<<SW_PLUS | 1<<SW_ENTER)
 
/* zusätzliche Timer in Abhängikeit vom Interrupttimer 0 - Keys */
#define TIMER0_1 50 // x * 10ms für Anzeige UBat
#define TIMER0_2 20 // x * 10ms für Bargraph und Diversity
#define TIMER0_3 2 // x * 10ms für RSSI Diversity
#define TIMER0_4 10 // x * 10ms für wi232 Nachführung Antenne
#define TIMER0_5 1000 // x * 10ms Hintergrundbeleuchtung 10 sekunden Schritte
#define BLINK_PERIOD 12 // abhängig von Tracking_GPS() in Task_0_4(void)
/* initiale Anfangswerte der Einstellungen */
#define EEP_INITB 75 // irgend ein Wert um beschriebenen EEPROM zu erkennen
#define VERSION "1.10"
#define CONTRAST3V 16 // 16 bei LCD 3,3V Bias 1/5 default Wert
#define CONTRAST5V 12 // 12 bei LCD 5V Bias 1/4
#define CONTRAST_MIN 0
#define CONTRAST_MAX 30
#define BACKGR_LIGHT 31 // Hintergrundbeleuchtung immer an
#define BACKGR_LIGHT_MIN 0 // Hintergrundbeleuchtung immer aus
#define BACKGR_LIGHT_MAX 31 // Hintergrundbeleuchtung immer an, z.Z.: Max = 5 Minuten
#define U_OFFSET 85 // um type float o. double zu vermeiden *100
#define U_OFFSET_MIN 0
#define U_OFFSET_MAX 200
#define U_MIN 960 // um type float o. double zu vermeiden *100
#define U_MIN_MIN 550 // auch für Lipo 2s
#define U_MIN_MAX 1400
#define CHANNEL 1 // default Wert
#define CHANNEL_MIN 1
#define CHANNEL_MAX 7
#define AV_SOURCE 0 // av1, av2, diversity
#define AV_SOURCE_MIN 0
#define AV_SOURCE_MAX 2
/* Toleranzen bei den RSSI-Spannungen ausgleichen */
#define UDBM_MIN 460 // RSSI geringste Feldstärke
#define UDBM_MAX 75 // RSSI größte Feldstärke
#define UDBM_KORR_FA 128 // Korrekturfaktor 1 * 128 RSSI1 korrigieren
/* Servokalibrierungen derzeit zu SERVO_STEPS = 255 skaliert */
#define SERVO_PAN 0
#define SERVO_TILT 1
#define SERVO_NUM_CHANNELS 2 // Anzahl der angeschlossen Servos max. 2!!!
#define SERVO_PERIODE 20 // default Angabe in ms
//prescaler 256
#define SERVO_I0_RIGHT 45 // default Wert, ca. 0,9ms
#define SERVO_I0_RIGHT_MIN 0 // Servokalibrierung Grenze der linken Position
#define SERVO_I0_RIGHT_MAX 100 // SERVO_MIN + SERVO_RIGHT
#define SERVO_I0_LEFT 45 // default Wert, ca. 2,1ms
#define SERVO_I0_LEFT_MIN 0 // Servokalibrierung ,Grenze der rechten Position
#define SERVO_I0_LEFT_MAX 100 // SERVO_MAX - SERVO_LEFT
#define SERVO_I0_MIDDLE SERVO_STEPS/2
#define SERVO_I0_MIDDLE_MIN SERVO_STEPS/2 - 25
#define SERVO_I0_MIDDLE_MAX SERVO_STEPS/2 + 25
//prescaler 64
#define SERVO_I1_RIGHT 180 // default Wert, ca. 0,9ms
#define SERVO_I1_RIGHT_MIN 0 // Servokalibrierung Grenze der linken Position
#define SERVO_I1_RIGHT_MAX 400 // SERVO_MIN + SERVO_RIGHT
#define SERVO_I1_LEFT 180 // default Wert, ca. 2,1ms
#define SERVO_I1_LEFT_MIN 0 // Servokalibrierung ,Grenze der rechten Position
#define SERVO_I1_LEFT_MAX 400 // SERVO_MAX - SERVO_LEFT
#define SERVO_I1_MIDDLE ((SERVO_STEPS + 1) * 4 - 1)/2
#define SERVO_I1_MIDDLE_MIN ((SERVO_STEPS + 1) * 4 - 1)/2 - 100
#define SERVO_I1_MIDDLE_MAX ((SERVO_STEPS + 1) * 4 - 1)/2 + 100
 
#define SERVO_REV 0 // kein Reverse
/* Antennen-Nachführung */
#define TRACKING_MIN 0 // aus, TRACKING_RSSI, TRACKING_GPS, TRACKING_MKCOCKPIT
#define TRACKING_MAX 3
/* Antennen-Nachführung per RSSI */
#define TRACKING_HYSTERESE 40 // Hysterese bevor Tracking bei Richtungswechsel anspricht
#define TRACKING_HYST_MIN 0
#define TRACKING_HYST_MAX 100
 
 
#endif /* CONFIG_H_ */
/NGVideo5_8/tags/v1.11/dogm.c
0,0 → 1,247
 
/****************************************************************/
/* */
/* NG-Video 5,8GHz */
/* */
/* Copyright (C) 2011 - gebad */
/* */
/* This code is distributed under the GNU Public License */
/* which can be found at http://www.gnu.org/licenses/gpl.txt */
/* */
/* using DOGM-Library 1.0. */
/* Copyright (C) 2010-averyfarwaydate Luca Bertoncello */
/* Hartigstrasse, 12 - 01127 Dresden Deutschland */
/* E-Mail: lucabert@lucabert.de, lucabert@lucabert.com */
/* http://www.lucabert.de/ http://www.lucabert.com/ */
/****************************************************************/
 
#include <util/delay.h>
 
#include "config.h"
#include "dogm.h"
#include <avr/pgmspace.h>
 
// Instruktionen mit ST7036 4 Bit Mode im "Extension mode"
#define CLEAR_DISPLAY 0b00000001
#define FUNCTION_SET_INIT_0 0b00110011 // 0x30 & 0x30 als nibble
#define FUNCTION_SET_INIT_1 0b00110010 // 0x30 & 0x20 als nibble
#define FUNCTION_SET_INIT_2 0b00101001 // 0x29 4-bit, 2 Zeilen, kein DoubleHeight, InstructionTable1
#define INSTRUCTION_Table_0 0b00101000 // Instruction table 0
#define INSTRUCTION_Table_1 0b00101001 // Instruction table 1
#define SET_CGRAM 0b01000000 // für user defined Char
#define BIAS_SET 0b00010101 // table 1 DB3=Bias 1/4, DB0=3 Zeilen 0b00011101
#define FOLLOWER_CONTROL 0b01101110 // nach Datenblattbsp. 3,3V DOGM bei 5V 0b01101100
#define CONTRAST_SET 0b01110000 // Kontrastwert Bit3 bis Bit0
#define POWER_CONTRAST 0b01010100 // Bit1 und Bit0 entspricht Kontrastwert Bit5 und Bit4 3,3V 0b0101 0100 5V 0b0101 0000
#define DISPLAY_ON 0b00001100
#define ENTRY_MODE 0b00000110 // Cursor Auto-Increment
#define SET_DDRAM_ADDR 0b10000000 // Bit7 bis Bit0 Adresse
#define BS 3 // 0 - 1/5 bias // 1 - 1/4 bias
#define RAB1 1 // select follower amplified ratio
#define BON 2 // set booster circuit on/off bei Power_Contrast
 
#define lcdSetEnable() LCD_E_PORT |= (1<<LCD_ENABLE);
#define lcdClearEnable() LCD_E_PORT &= ~(1<<LCD_ENABLE);
#define lcdSetRegSelect() LCD_RS_PORT |= (1<<LCD_REGSELECT)
#define lcdClearRegSelect() LCD_RS_PORT &= ~(1<<LCD_REGSELECT)
 
 
 
/************************************************************************/
/* Definieren eines Sonderzeichen */
/* Parameter: */
/* uint8_t lcd_addr : Adresse, 1.Adresse 0 */
/* char *lcd_zeichen: Zeiger auf das 1. Byte der Zeichendefinition */
/* */
/************************************************************************/
void lcdWriteCGRAM(uint8_t lcd_addr, char *lcdChr)
{ int8_t i;
 
lcdSendInstruction(INSTRUCTION_Table_0);
for(i = 0; i < 8; i++)
{
lcdSendInstruction(SET_CGRAM | (lcd_addr * 8 + i)); // CG RAM Adresse
//lcdPutc(lcdChr[i]); // Data Write 8x Pixelzeile
lcdPutc(pgm_read_byte(&lcdChr[i])); // array im Flash
}
lcdSendInstruction(INSTRUCTION_Table_1);
}
 
/************************************************************************/
/* Definieren von n <= 8 Sonderzeichen */
/* Parameter: */
/* SpecialChr_t lcdChr : Array mit Sonderzeichen */
/* uint8_t quantity : Anzahl der zu übertragenen Sonderzeichen */
/* */
/************************************************************************/
void lcdWriteCGRAM_Array(SpecialChr_t lcdChr, uint8_t quantity)
{
for (uint8_t i = 0; i < quantity; i++)
lcdWriteCGRAM(i, lcdChr[i]); // Sonderzeichen in CGRAM der LCD schreiben
}
 
/************************************************************************************/
/* sendet ein Nibble (4 Bit) zum LCD-Controller */
/* Parameter: */
/* char data :Byte */
/* */
/************************************************************************************/
void lcdSendNibble(char data)
{
LCD_DATA_PORT |= (data & 0x0f);
LCD_DATA_PORT &= (data | 0xf0);
lcdSetEnable();
_delay_us(2);
lcdClearEnable();
_delay_us(30); // nach Datenblatt > 26,3µs
}
 
/************************************************************************************/
/* sendet 8 Bit (2 Nibble) zum LCD-Controller */
/* Parameter: */
/* char data :Byte */
/* */
/************************************************************************************/
void lcdSendByte(char data)
{
lcdSendNibble(data>>4);
lcdSendNibble(data);
}
 
/************************************************************************************/
/* sendet instruction zum LCD-Controller */
/* Parameter: */
/* char instruction :Byte */
/* */
/************************************************************************************/
void lcdSendInstruction(char instruction)
{
lcdClearRegSelect(); // LCD-RS für Instruktionen
lcdSendByte(instruction);
}
 
/************************************************************************************/
/* sendet ein Zeichen zum LCD-Display */
/* Parameter: */
/* char c :Zeichen */
/* */
/************************************************************************************/
void lcdPutc(char c)
{
lcdSetRegSelect(); // LCD-RS für Daten
lcdSendByte(c);
}
 
/************************************************************************************/
/* sendet einen String zum LCD-Display */
/* Parameter: */
/* char *str :Zeichenkette */
/* */
/************************************************************************************/
void lcdPuts(char *str)
{
uint8_t l;
uint8_t pos = 0;
 
for(l = 0; str[l] != 0; l++)
// funtioniert nur von Zeile 0 an, da aktuelle Zeile nicht bekannt! Kein read!
// man könnte pos bei lcdSendByte, lcdGotoXY und lcdClear abhängig von Steuerung mitzählen
if(str[l] == '\n')
{
if (pos >= LCD_LINES)
pos = 0;
else
pos++;
lcdGotoXY(0, pos);
}
else
lcdPutc(str[l]);
}
 
/************************************************************************************/
/* Löscht Inhalt auf LCD-Display */
/* */
/************************************************************************************/
void lcdClear()
{
lcdSendInstruction(CLEAR_DISPLAY);
_delay_ms(2);
}
 
/************************************************************************************/
/* Setzt Kontrast auf LCD-Display */
/* Parameter: */
/* uint8_t contrast :Wert vo 0 bis max 63 */
/* */
/************************************************************************************/
void lcdContrast(uint8_t dogm, uint8_t contrast)
{ uint8_t power_contrast = POWER_CONTRAST;
 
if(dogm == DOGM5V) {
power_contrast &= ~(1<<BON);
}
lcdSendInstruction(INSTRUCTION_Table_1);
lcdSendInstruction(CONTRAST_SET | (contrast & 0x0F));
lcdSendInstruction(power_contrast | ((contrast>>4) & 0x03));
}
 
//***********************************************************************************/
/* Setzt setzt den Cursor zur Position x/y */
/* Parameter: */
/* uint8_t x, :Position Spalte */
/* uint8_t y, :Position Zeile */
/* */
/************************************************************************************/
void lcdGotoXY(uint8_t x, uint8_t y)
{ uint8_t pos;
 
if(x > LCD_COLS) x = 0;
if(y > LCD_LINES) y = 0;
pos = y * LCD_COLS + x;
lcdSendInstruction(SET_DDRAM_ADDR | pos);
}
 
/************************************************************************************/
/* Initialisiert den LCD-Controller und der Atmega-Ausgänge */
/* Parameter: */
/* uint8_t dogm :0=3,3V oder 1=5V DOGM */
/* uint8_t contrast :Wert vo 0 bis max 63 */
/* uint8_t cursor :Darstellung des Cursors ein oder 0 aus */
/* uint8_t blink :Cursor blinken, 0 kein blinken */
/* */
/************************************************************************************/
void lcdInit(uint8_t dogm, uint8_t contrast, uint8_t cursor, uint8_t blink)
{ uint8_t bias_set = BIAS_SET;
uint8_t follower_ctrl = FOLLOWER_CONTROL;
uint8_t power_contrast = POWER_CONTRAST;
 
LCD_BACKLIGHT_DDR |= (1<<LCD_BACKLIGHT);
LCD_E_DDR |= (1<<LCD_ENABLE);
LCD_RS_DDR |= (1<<LCD_REGSELECT);
LCD_DATA_DDR |= (1<<LCD_DATA7) | (1<<LCD_DATA6) | (1<<LCD_DATA5) | (1<<LCD_DATA4);
 
lcdClearEnable();
_delay_ms(40); // lt. Datenblatt muss > 40ms nach Power On or ext. Reset
 
if(dogm == DOGM5V) {
follower_ctrl &= ~(1<<RAB1);
bias_set |= (1 << BS);
power_contrast &= ~(1<<BON);
}
 
//Initialisierung für DOGM (mit ST7036) 4 Bit Mode
lcdClearRegSelect(); // LCD-RS für Instruktionen
lcdSendNibble(FUNCTION_SET_INIT_0>>4);
_delay_ms(2); // lt. Datenblatt muss > 1,6ms Pause nach ersten Nibble
lcdSendNibble(FUNCTION_SET_INIT_0);
lcdSendInstruction(FUNCTION_SET_INIT_1);
lcdSendInstruction(FUNCTION_SET_INIT_2);
lcdSendInstruction(bias_set);
lcdSendInstruction(CONTRAST_SET | (contrast & 0x0F));
lcdSendInstruction(power_contrast | ((contrast>>4) & 0x03));
lcdSendInstruction(follower_ctrl);
lcdSendInstruction(INSTRUCTION_Table_0);
lcdSendInstruction(DISPLAY_ON | (cursor & 0x01) << 1 | (blink & 0x01));
lcdClear();
lcdSendInstruction(ENTRY_MODE);
}
/NGVideo5_8/tags/v1.11/dogm.h
0,0 → 1,42
 
/****************************************************************/
/* */
/* NG-Video 5,8GHz */
/* */
/* Copyright (C) 2011 - gebad */
/* */
/* This code is distributed under the GNU Public License */
/* which can be found at http://www.gnu.org/licenses/gpl.txt */
/* */
/* using DOGM-Library 1.0. */
/* Copyright (C) 2010-averyfarwaydate Luca Bertoncello */
/* Hartigstrasse, 12 - 01127 Dresden Deutschland */
/* E-Mail: lucabert@lucabert.de, lucabert@lucabert.com */
/* http://www.lucabert.de/ http://www.lucabert.com/ */
/****************************************************************/
 
#ifndef DOGM_H_
#define DOGM_H_
 
#include <avr/io.h>
 
#define DOGM3V 0 // 3,3V DOGM
#define DOGM5V 1 // 5V DOGM
 
typedef char SpecialChr_t[6][8];
 
void lcdWriteCGRAM(uint8_t lcd_addr, char *lcdChr); // write a char string to CGRAM
void lcdWriteCGRAM_Array(SpecialChr_t lcdChr, uint8_t quantity); // write a array of char string to CGRAM
void lcdSendByte(char data);
void lcdSendInstruction(char instruction);
void lcdPutc(char c);
void lcdPuts(char *str);
void lcdClear(void);
void lcdContrast(uint8_t dogm, uint8_t contrast);
void lcdGotoXY(uint8_t x, uint8_t y);
void lcdInit(uint8_t dogm, uint8_t contrast, uint8_t cursor, uint8_t blink);
 
#define lcdBacklightOn() LCD_BACKLIGHT_PORT |= (1<<LCD_BACKLIGHT);
#define lcdBacklightOff() LCD_BACKLIGHT_PORT &= ~(1<<LCD_BACKLIGHT);
 
#endif /* DOGM_H_ */
/NGVideo5_8/tags/v1.11/keys.c
0,0 → 1,135
 
/************************************************************************/
/* */
/* Debouncing 8 Keys */
/* Sampling 4 Times */
/* With Repeat Function */
/* */
/* Author: Peter Dannegger */
/* danni@specs.de */
/* */
/* ergänzt: gebad, beschschleunigende Tastenwiederholung */
/* */
/************************************************************************/
 
#include <stdint.h>
#include <avr/io.h>
#include <avr/interrupt.h>
 
#include "keys.h"
#include "config.h"
 
ISR( TIMER0_OVF_vect ) // every 10ms
{
static uint8_t ct0, ct1, rpt, timer0_1, timer0_2, timer0_3, timer0_4;
static uint16_t timer0_5 = TIMER0_5;
uint8_t i, key_pin;
 
TCNT0 = (uint8_t)(int16_t)-(F_CPU / 1024 * 10e-3 + 0.5); // preload for 10ms
 
key_pin = (KEY_MP_PIN & ( (1<<KEY_MINUS) | (1<<KEY_PLUS)));
key_pin |= (KEY_ENTER_PIN & (1<<KEY_ENTER)) >> 2;// move enter bit to sw_enter bit
i = key_state ^ ~key_pin; // key changed ?
ct0 = ~( ct0 & i ); // reset or count ct0
ct1 = ct0 ^ (ct1 & i); // reset or count ct1
i &= ct0 & ct1; // count until roll over ?
key_state ^= i; // then toggle debounced state
key_press |= key_state & i; // 0->1: key press detect
if (key_press & REPEAT_MASK) { // da bei mir alle Tasten in REPEAT_MASK
light_count = 0; // wenn keine Taste gedrückt beginnt Zähler für Hintergrundbeleuchtung aus
timer0_5 = TIMER0_5;
}
if( (key_state & REPEAT_MASK) == 0 ) { // check repeat function
rpt = REPEAT_START; // start delay
key_repeat_next = REPEAT_NEXT; // Wert bestimmt Tasten-Beschleunigung/-Wiederholrate beginnt, mit 200ms
key_counter = REPEAT_ACC_N; // wenn V_REPEAT, nach dem angegebenen Zeichen beschleunigen
}
if( --rpt == 0 ){
rpt = key_repeat_next; // repeat delay
key_rpt |= key_state & REPEAT_MASK;
}
if ( --timer0_1 == 0) {
timer0_1 = TIMER0_1;
task_timer0_1 = 1;
}
if ( --timer0_2 == 0) {
timer0_2 = TIMER0_2;
task_timer0_2 = 1;
}
if ( --timer0_3 == 0) {
timer0_3 = TIMER0_3;
task_timer0_3 = 1;
}
if ( --timer0_4 == 0) {
timer0_4 = TIMER0_4;
task_timer0_4 = 1;
}
if ( --timer0_5 == 0) {
timer0_5 = TIMER0_5;
task_timer0_5 = 1;
}
}
 
///////////////////////////////////////////////////////////////////
//
// check if a key has been pressed. Each pressed key is reported
// only once
//
uint8_t Get_Key_Press( uint8_t key_mask )
{
cli(); // read and clear atomic !
key_mask &= key_press; // read key(s)
key_press ^= key_mask; // clear key(s)
sei();
return key_mask;
}
 
///////////////////////////////////////////////////////////////////
//
// check if a key has been pressed long enough such that the
// key repeat functionality kicks in. After a small setup delay
// the key is reported beeing pressed in subsequent calls
// to this function. This simulates the user repeatedly
// pressing and releasing the key.
//
uint8_t Get_Key_Rpt( uint8_t key_mask )
{
cli(); // read and clear atomic !
key_mask &= key_rpt; // read key(s)
key_rpt ^= key_mask; // clear key(s)
sei();
return key_mask;
}
 
///////////////////////////////////////////////////////////////////
//
uint8_t Get_Key_Short( uint8_t key_mask )
{
cli(); // read key state and key press atomic !
return Get_Key_Press( ~key_state & key_mask );
}
 
///////////////////////////////////////////////////////////////////
//
uint8_t Get_Key_Long( uint8_t key_mask )
{
return Get_Key_Press( Get_Key_Rpt( key_mask ));
}
 
void Key_Speedup_rpt( uint8_t speedup )
{
if (speedup) {
if (key_counter > 0) { // nach x Zeichen wird Wiederholrate kontinuierlich erhöht
cli();
key_counter--;
sei();
}
else {
if (key_repeat_next > 3) { // Wert bestimmt die max. Beschleunigung/Wiederholrate
cli(); // kann jedoch nicht kleiner 10ms sein
key_repeat_next -= 2;
sei();
}
}
}
}
/NGVideo5_8/tags/v1.11/keys.h
0,0 → 1,43
 
/************************************************************************/
/* */
/* Debouncing 8 Keys */
/* Sampling 4 Times */
/* With Repeat Function */
/* */
/* Author: Peter Dannegger */
/* danni@specs.de */
/* */
/* ergänzt: gebad, beschschleunigende Tastenwiederholung */
/* */
/************************************************************************/
 
#ifndef KEYS_H_
#define KEYS_H_
 
#define REPEAT_START 50 // after 500ms
#define REPEAT_NEXT 20 // every 200ms
#define REPEAT_ACC_N 6 // wenn V_REPEAT, nach dem angegebenen Zeichen beschleunigen
 
volatile uint8_t key_state; // debounced and inverted key state:
// bit = 1: key pressed
volatile uint8_t key_press; // key press detect
volatile uint8_t key_rpt; // key long press and repeat
volatile uint8_t key_repeat_next;
volatile uint8_t key_counter;
 
volatile uint8_t task_timer0_1;
volatile uint8_t task_timer0_2;
volatile uint8_t task_timer0_3;
volatile uint8_t task_timer0_4;
volatile uint8_t task_timer0_5;
 
uint8_t Get_Key_Press( uint8_t key_mask );
uint8_t Get_Key_Rpt( uint8_t key_mask );
uint8_t Get_Key_Short( uint8_t key_mask );
uint8_t Get_Key_Long( uint8_t key_mask );
void Key_Speedup_rpt( uint8_t speedup );
 
volatile uint16_t light_count; // muss bei jeden Tastendruck auf 0 gesetzt werdwn
 
#endif /* KEYS_H_ */
/NGVideo5_8/tags/v1.11/main.c
0,0 → 1,118
 
/****************************************************************/
/* */
/* NG-Video 5,8GHz */
/* */
/* Copyright (C) 2011 - gebad */
/* */
/* This code is distributed under the GNU Public License */
/* which can be found at http://www.gnu.org/licenses/gpl.txt */
/* */
/****************************************************************/
 
#include <string.h>
#include <avr/interrupt.h>
 
#include "servo.h"
#include "config.h"
#include "dogm.h"
#include "keys.h"
#include "ngvideo.c"
#include "menue.c"
#include "usart.h"
 
 
int main(void)
{ uint8_t ep_reset = 1;
uint8_t val;
// LCD selbst definierte Sonderzeichen, RSSI-Balken und wi232 Empfang Daten im Flash
// deshalb in dogm.c lcdPutc(pgm_read_byte(&lcdChr[i]));
static SpecialChr_t lcdSpecialChr PROGMEM = {{32,32,16,16,16,16,32,32},\
{32,32,24,24,24,24,32,32},\
{32,32,28,28,28,28,32,32},\
{32,32,30,30,30,30,32,32},\
{32,32,31,31,31,31,32,32},\
{6,8,20,19,20,8,6,32}};
 
 
_delay_ms(100); // Einschaltstörungen unterdrücken
 
DDRB |= (1<<POWER);
PORTB &= ~(1<<POWER); //NOT(SHDN) LT1776
 
// switch init
KEY_MP_DDR &= ~((1<<KEY_MINUS) | (1<<KEY_PLUS));
KEY_ENTER_DDR &= ~((1<<KEY_ENTER));
// auf default rücksetzen - Tasten direkt lesen, da noch kein Interrupt
if( !(KEY_MP_PIN & ((1<<KEY_MINUS) | (1<<KEY_PLUS))))
--ep_reset;
 
Init_EEPROM(ep_reset);
 
// auf DOGM 5V/3,3V rück-/setzen - Tasten direkt lesen, da noch kein Interrupt
if(!((KEY_ENTER_PIN & (1<<KEY_ENTER)) || (KEY_MP_PIN & (1<<KEY_PLUS))))
Set_DOGM_Version();
 
DDRA |= (1<<CHANNel_12) | (1<<CHANNel_11) | (1<<CHANNel_10) | (1<<MUX_IN) | (1<<MUX_EN);
DDRB |= (1<<BEEPER) | (1<<CHANNel_02) | (1<<CHANNel_01) | (1<<CHANNel_00);
Set_Channel(channel);
ch_stored = channel;
PORTA &= ~(1<<MUX_EN); // MUX enable
 
ADC_Init();
// Timer 0 für Tasten und Anzeigen(Task's)
TCCR0B = (1<<CS02)|(1<<CS00); // divide by 1024
TIMSK0 |= 1<<TOIE0; // 8 bit Timer/Counter0 Overflow Interrupt aktiviert
 
// Timer 2 für Diversity vSync und GPS-Tracking MK Datensatz senden
TCCR2B = (1<<CS21) | (1<<CS20); // divide by 64
TIMSK2 |= 1<<TOIE2; // 8 bit Timer/Counter2 Overflow Interrupt aktiviert
 
// Interrupt für sync - RX-Umschaltung bei Diversity
DDRD &= ~((1<<VSYNC1) | (1<<VSYNC0));
//EICRA |= (1<<ISC11) | (1<<ISC10) | (1<<ISC01) | (1<<ISC00);// interrupt on INT0 and INT1 pin rising edge
EICRA |= (1<<ISC11) | (1<<ISC01);// interrupt on INT0 and INT1 pin falling edge
Set_AV_Source(av_source); // MUX auf av-x setzen; EIMSK Int0 und Int1 für Sync-Diversity ein
 
DDRD |= (1<<SERVO1) | (1<<SERVO2); // Servoports als Ausgang
if (tracking > TRACKING_MIN) // Servos sind nur bei Tracking und Servokalibrierung zugeschaltet
servoInit();
 
// LCD init
lcdInit(dogm_vers, contrast, 0, 0);
lcd_BackgrLight_On();
lcdWriteCGRAM_Array(lcdSpecialChr, 6);
 
Displ_Version();
Double_Beep(DBEEPVERS, DBEEPVERSP);
 
sei();
 
if (language == NO_LANGUAGE) {
language = GERMAN; // Beim Einschalten pmenu[] vordefiniert mit "0"
Menu_Language();
}
pmenu[0] = '\0'; // falls GPS-Antennennachführung ==> Empfang blinken
 
Displ_Main_Disp();
 
while(1)
{
Task_0_1();
Task_0_2();
Tasks_unvisible();
if (bat_low != 0) {
if (Get_Key_Short( 1<<SW_ENTER )) {
m_pkt = 1; // 0 wäre "zurück", so aber ins Untermenü immer erster Menüpunkt
Menu_Main();
}
val = Change_Value_plmi(channel, CHANNEL_MIN, CHANNEL_MAX, 0, 0, Displ_Channels, 1, C_REPEAT);
if (val != channel) { // nicht bei jeden Schleifendurchlauf Set_Channel()
channel = val;
Set_Channel(channel);
}
}
}
}
/NGVideo5_8/tags/v1.11/makefile
0,0 → 1,411
# WinAVR Sample makefile written by Eric B. Weddington, Jörg Wunsch, et al.
# Released to the Public Domain
# Please read the make user manual!
#
# Additional material for this makefile was submitted by:
# Tim Henigan
# Peter Fleury
# Reiner Patommel
# Sander Pool
# Frederik Rouleau
# Markus Pfaff
#
# On command line:
#
# make all = Make software.
#
# make clean = Clean out built project files.
#
# make coff = Convert ELF to AVR COFF (for use with AVR Studio 3.x or VMLAB).
#
# make extcoff = Convert ELF to AVR Extended COFF (for use with AVR Studio
# 4.07 or greater).
#
# make program = Download the hex file to the device, using avrdude. Please
# customize the avrdude settings below first!
#
# make filename.s = Just compile filename.c into the assembler code only
#
# To rebuild project do "make clean" then "make all".
#
 
# MCU name
MCU = atmega644
 
## 16500000 is for attiny45/85/461/861 only (RC+PLL mode)
#CLK = 12000000UL
#CLK = 15000000UL
#CLK = 16000000UL
#CLK = 16500000UL
CLK = 20000000UL
#CLK = 18432000UL
 
#Fuse settings for ATmega644
ifeq ($(MCU), atmega644)
FUSE_BITS = -u -U lfuse:w:0xef:m -U hfuse:w:0xd9:m -U efuse:w:0xfd:m
HEX_FILE_NAME = MEGA644
endif
 
# Output format. (can be srec, ihex, binary)
FORMAT = ihex
 
# Target file name (without extension).
TARGET = Hexfiles/NGVideo_$(HEX_FILE_NAME)
 
# 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
 
# If there is more than one source file, append them above, or modify and
# uncomment the following:
SRC = main.c dogm.c keys.c servo.c usart.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 =
 
 
# 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
 
 
 
# 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 = AVR910
#AVRDUDE_PROGRAMMER = stk200
AVRDUDE_PROGRAMMER = USBasp
 
AVRDUDE_PORT = usb # programmer connected to USB port
#AVRDUDE_PORT = com1 # programmer connected to serial device
#AVRDUDE_PORT = lpt1 # programmer connected to parallel port
 
AVRDUDE_WRITE_FLASH = -U flash:w:$(TARGET).hex $(FUSE_BITS)
AVRDUDE_WRITE_EEPROM = -U eeprom:w:$(TARGET).eep
 
#AVRDUDE_FLAGS = -p $(MCU) -P $(AVRDUDE_PORT) -b 115200 -c $(AVRDUDE_PROGRAMMER)
AVRDUDE_FLAGS = -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
 
# 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-20090313
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) -DF_CPU=$(CLK) -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
 
/NGVideo5_8/tags/v1.11/menue.c
0,0 → 1,1275
 
/****************************************************************/
/* */
/* NG-Video 5,8GHz */
/* */
/* Copyright (C) 2011 - gebad */
/* */
/* This code is distributed under the GNU Public License */
/* which can be found at http://www.gnu.org/licenses/gpl.txt */
/* */
/****************************************************************/
 
#include <util/delay.h>
 
#include "config.h"
#include "ngvideo.h"
#include "keys.h"
#include "menue.h"
#include "servo.h"
#include "messages.c"
 
typedef uint8_t scr_menu_t[SCROLL_MAIN_MAX + 3]; // einmal, da Index mit 0 beginnt plus Vergrößerung für 2 zusätzlich eingeblendete Punkte
uint8_t m_pkt; // um bei Rücksprung auf ursprünglichen Arrayeintrag(Menüpunkt), Scroll_Menu zeigen
uint8_t servo_nr; // zwischen Servo 1 und 2 wird nur mit global servo_nr unterschieden
 
// Menügliederung im Flash belassen
const char cmdStr0[] PROGMEM = "0";
const char cmdStr01[] PROGMEM = "01";
const char cmdStr02[] PROGMEM = "02";
const char cmdStr03[] PROGMEM = "03";
const char cmdStr031[] PROGMEM = "031";
const char cmdStr032[] PROGMEM = "032";
const char cmdStr04[] PROGMEM = "04";
const char cmdStr05[] PROGMEM = "05";
const char cmdStr051[] PROGMEM = "051";
const char cmdStr052[] PROGMEM = "052"; // zwischen Servo 1 und 2 wird danach
const char cmdStr0521[] PROGMEM = "0521"; // mit global servo_nr unterschieden
const char cmdStr0522[] PROGMEM = "0522";
const char cmdStr0523[] PROGMEM = "0523";
const char cmdStr0524[] PROGMEM = "0524";
const char cmdStr053[] PROGMEM = "053";
const char cmdStr0531[] PROGMEM = "0531";
const char cmdStr0532[] PROGMEM = "0532";
const char cmdStr0533[] PROGMEM = "0533";
const char cmdStr0534[] PROGMEM = "0534";
const char cmdStr06[] PROGMEM = "06";
const char cmdStr061[] PROGMEM = "061";
const char cmdStr062[] PROGMEM = "062";
const char cmdStr07[] PROGMEM = "07";
const char cmdStr071[] PROGMEM = "071";
const char cmdStr072[] PROGMEM = "072";
const char cmdStr08[] PROGMEM = "08";
const char cmdStr09[] PROGMEM = "09"; // wird nur bei Tracking RSSI oder GPS eingeblendet - SCROLL_MAIN_MAX wird geändert
const char cmdStr0d[] PROGMEM = "0:"; // wird nur bei Tracking GPS eingeblendet - SCROLL_MAIN_MAX wird geändert
const char cmdStr0d1[] PROGMEM = "0:1"; // nach '9' (0x39) folgt ':' (0x3a)
const char cmdStr0d2[] PROGMEM = "0:2";
const char cmdStr0d3[] PROGMEM = "0:3";
const char cmdStr0d4[] PROGMEM = "0:4";
 
command_table_t command_table[] PROGMEM = // Befehls-Tabelle
{
{cmdStr0, Menu_Main},
{cmdStr01, Menu_AV_Source},
{cmdStr02, Menu_RX_Channel},
{cmdStr03, Menu_RSSI_Calibr},
{cmdStr031, Menu_RSSI_min},
{cmdStr032, Menu_RSSI_max},
{cmdStr04, Menu_Language},
{cmdStr05, Menu_Servo_Calibr},
{cmdStr051, Menu_Servo_Steps},
{cmdStr052, Menu_Servo1}, // zwischen Servo 1 und 2 wird danach
{cmdStr0521, Menu_Servo1_rev}, // mit global servo_nr unterschieden
{cmdStr0522, Menu_Servo1_left},
{cmdStr0523, Menu_Servo1_right},
{cmdStr0524, Menu_Servo1_middle},
{cmdStr053, Menu_Servo2},
{cmdStr0531, Menu_Servo2_rev},
{cmdStr0532, Menu_Servo2_left},
{cmdStr0533, Menu_Servo2_right},
{cmdStr0534, Menu_Servo2_middle},
{cmdStr06, Menu_lcd},
{cmdStr061, Menu_lcd_Contrast},
{cmdStr062, Menu_lcd_Backgr_Light},
{cmdStr07, Menu_Battery},
{cmdStr071, Menu_Low_U_Setup},
{cmdStr072, Menu_U_Offset},
{cmdStr08, Menu_Tracking_Ant},
{cmdStr09, Menu_Tracking_Option}, // wird nur bei Tracking RSSI oder GPS eingeblendet - SCROLL_MAIN_MAX wird geändert
{cmdStr0d, Menu_GPS_Display}, // wird nur bei Tracking GPS eingeblendet - SCROLL_MAIN_MAX wird geändert
{cmdStr0d1, Menu_GPS_Display_FLAG}, // nach '9' (0x39) folgt ':' (0x3a)
{cmdStr0d2, Menu_GPS_Display_FLAG},
{cmdStr0d3, Menu_GPS_Display_FLAG},
{cmdStr0d4, Menu_GPS_Displ_RX_Time}
};
 
 
typedef void (*Displ_Fnct_t)( uint32_t );
uint32_t Change_Value(uint32_t val, uint32_t min_val, uint32_t max_val, uint8_t pos, Displ_Fnct_t Displ_Fnct, uint8_t vrepeat);
void Displ_AV_Source(uint32_t q);
void Displ_Channels(uint32_t k);
void Displ_Set_Contrast(uint32_t val);
void Displ_Backgr_Light(uint32_t val);
void Displ_U_2Nk(uint32_t u);
void Displ_Off_On(uint32_t val);
void Displ_Language(uint32_t q);
void Displ_Servo_Steps(uint32_t val);
void Displ_Servo_Min(uint32_t val);
void Displ_Servo_Max(uint32_t val);
void Displ_Servo_Mid(uint32_t val);
void Displ_Format_Int(uint32_t val);
void Displ_sel_Tracking(uint32_t q);
void Displ_track_TX(uint32_t q);
void Displ_Baudrate(uint32_t q);
 
 
/**************************************************************/
/* */
/* Steuerung der Menüs */
/* */
/**************************************************************/
 
/************************************************************************************/
/* sucht nach übergebenen String in der Kommandotabelle und springt zum daneben */
/* stehenden Menü-Programm */
/* Parameter: */
/* char *pmenu :zu suchender String in Kommandotabelle */
/* */
/************************************************************************************/
void Jump_Menu(char *pmenu)
{ uint8_t i;
void (*func)(void);
 
if (pmenu[0] != '\0'){
for (i=0; i < sizeof(command_table) / sizeof(command_table_t); i++) {
// Ist das der gesuchte String?
if (!(strcmp_P(pmenu, (char*)pgm_read_word(&(command_table[i].menu_nr))))) {
func = (void(*)(void))pgm_read_word(&(command_table[i].fp));
func();
break;
}
}
}
}
 
/************************************************************************************/
/* */
/* Abfrage Short- oder Long-Enter */
/* verbleibt in Abfrage bis Enter betätigt; Rückgabe => Short-Enter True/False */
/* */
/************************************************************************************/
void Long_Enter(void)
{
Tasks_unvisible();
// falls Akku leer ==> Menü verlassen und Anzeige __ACCU_LOW
U_Messen_cmp(DISABLE_BTIMER);
if ((Get_Key_Long( 1<<SW_ENTER )) || (bat_low == 0)) pmenu[0] ='\0'; // direkt in das Hauptprogramm
}
 
uint8_t Short_Enter(void)
{
// bis Short- oder Long-Enter, auch Akku leer
while( !Get_Key_Short( 1<<SW_ENTER ) && (pmenu[0] !='\0')) {
Long_Enter();
}
lcdClear();
if (pmenu[0] == '\0') Displ_Main_Disp(); else Beep(BEEPENTER); // bei ShortEnter Beep
return(pmenu[0] != '\0'); // ShortEnter bringt 1 zurück
}
 
/************************************************************************************/
/* */
/* Unterprogramm vom Scroll_Menu(...) stellt Menüpunkte dar */
/* Parameter: */
/* scr_menu_t scr_menu : Array mit Strings der Menüanzeige */
/* uint8_t scr_idx : ausgewählter Menüpunkt */
/* uint8_t scroll_max: scrollen bis Wert */
/* */
/************************************************************************************/
void Displ_Scroll_Menu(scr_menu_t scr_menu, uint8_t scr_idx, uint8_t scroll_max)
{
uint8_t i;
const uint8_t p = 2; // LCD Beginn x-Position
if (scr_idx > 0) scr_idx--; else scr_idx = scroll_max;
for (i = 0; i < LCD_LINES; i++) {
lcdGotoXY(p, i);
lcdPuts(Msg(scr_menu[scr_idx]));
// ab Stringende bis zum Zeilenende löschen; LCD löschen flackert sonst zu sehr
for (int8_t n = LCD_COLS - strlen(Msg(scr_menu[scr_idx])) - p; n > 0; n--)
lcdPutc(' ');
if (scr_idx < scroll_max) scr_idx++; else scr_idx = 0;
}
}
 
/************************************************************************************/
/* */
/* Unterprogramm vom Scroll_Menu(...) und Change_Value(...) */
/* bei Rücksprung auf ursprünglichen Menüpunkt zeigen */
/* Parameter: */
/* uint8_t l : Strinlänge von pmenue */
/* */
/************************************************************************************/
void return_m_pkt(uint8_t l)
{
if (l > 0) {
l--;
m_pkt = pmenu[l] - '0'; // um bei Rücksprung auf ursprünglichen Arrayeintrag(Menüpunkt) zeigen
pmenu[l] ='\0'; // auf letztes Zeichen Stringende schreiben
}
if (l == 0) Displ_Main_Disp();
}
 
/************************************************************************************/
/* */
/* scrollt Menü über Mehrzeilige LCD */
/* */
/* Taste<Enter> lang springt in Hauptanzeige, kurz geht in den angewälten Menüpunkt*/
/* Taste<+> eine Zeile nach oben */
/* Taste<-> eine Zeile nach unten */
/* Parameter: */
/* scr_menu_t scr_menu : Array mit Strings der Menüanzeige */
/* uint8_t scroll_max: scrollen bis Wert */
/* uint8_t scr_idx : Index für array von Displ_Scroll_Menu(...) */
/* */
/************************************************************************************/
void Scroll_Menu(scr_menu_t scr_menu, uint8_t scroll_max, uint8_t scr_idx)
{ uint8_t l;
 
// pmenu[1] == '\0' entspricht <wenn Hauptmenue>, da jetzt nur noch Servo x für Scrollemenue (rev,min,max,mid)
if ((pmenu[1] == '\0') && ((tracking == TRACKING_RSSI) || (tracking == TRACKING_GPS) || (tracking == TRACKING_MKCOCKPIT))) {
++scroll_max;
if (tracking == TRACKING_RSSI) scr_menu[scroll_max] = MSG_TRACK_SERVO_HYTERESE;
if (tracking == TRACKING_GPS) {
scr_menu[scroll_max] = MSG_TRACK_TX_OSD_DATA;
++scroll_max; // zusätzliche Anzeige zu GPS
}
if (tracking == TRACKING_MKCOCKPIT) scr_menu[scroll_max] = MSG_COM;
}
lcdClear();
lcdGotoXY(0, 1);
lcdPutc(MARKER_SELECT); // '>>'
Displ_Scroll_Menu(scr_menu, scr_idx, scroll_max);
// bis Menueeingabe bestätigt oder zum vorherigen Menue
while( !Get_Key_Short( 1<<SW_ENTER ) && (pmenu[0] !='\0'))
{
// >> Menueauswahl nach oben
if( Get_Key_Press( 1<<SW_PLUS ) || Get_Key_Rpt( 1<<SW_PLUS ))
{
if (scr_idx > 0) scr_idx--; else scr_idx = scroll_max;
Displ_Scroll_Menu(scr_menu, scr_idx, scroll_max);
}
// >> Menueauswahl nach unten
if( Get_Key_Press( 1<<SW_MINUS ) || Get_Key_Rpt( 1<<SW_MINUS ))
{
if (scr_idx < scroll_max) scr_idx++; else scr_idx = 0;
Displ_Scroll_Menu(scr_menu, scr_idx, scroll_max);
}
Long_Enter();
}
lcdClear();
if ((pmenu[0] !='\0')) {
l = strlen(pmenu);
if (scr_idx > 0) {
m_pkt = 1; // 0 wäre "zurück", so aber ins Untermenü immer erster Menüpunkt
pmenu[l] = scr_idx + '0'; // nächsten MenueIndex anhängen 1 oder 2 oder ...
pmenu[l + 1] ='\0';
Beep(BEEPENTER);
}
else {
return_m_pkt(l); // um bei Rücksprung auf ursprünglichen Menüpunkt zeigen oder Displ_Main_Disp()
}
}
else
Displ_Main_Disp();
}
 
/************************************************************************************/
/* */
/* Ändern der Werte mit Tasten +,- und Anzeige */
/* z.B. für U-Offset, Batterie leer Eingabe ... */
/* */
/* Parameter: */
/* uint32_t val :zu ändernter Wert */
/* uint32_t min_val, max_val :min, max Grenze Wert ändern darf */
/* uint8_t posX, posY :Darstellung Wert xPos, YPos auf LCD */
/* Displ_Fnct_t Displ_Fnct :Index um variable Display Funktion aufzurufen */
/* uint8_t cycle :0 begrenzt Anzeige bei man_val, bzw. max_val */
/* :1 springt nach max_val auf min_val und umgedreht */
/* uint8_t vrepeat :beschleunigte Repeat-Funktion aus/ein */
/* uint32_t Change_Value_plmi(...) :Rückgabe geänderter Wert */
/* */
/************************************************************************************/
uint32_t Change_Value_plmi(uint32_t val, uint32_t min_val, uint32_t max_val, uint8_t posX, uint8_t posY, \
Displ_Fnct_t Displ_Fnct, uint8_t cycle, uint8_t vrepeat)
{
// >> Menueauswahl nach oben
if( Get_Key_Press( 1<<SW_PLUS ) || Get_Key_Rpt( 1<<SW_PLUS )){
if (val < max_val) {
val++;
Key_Speedup_rpt(vrepeat); // beschleunigte Repeat-Funktion
}
else
if (cycle) {
val = min_val;
}
lcdGotoXY(posX, posY); // lcd Position Wert
Displ_Fnct(val); // geänderten Wert darstellen, je nach Menüpunkt
}
// >> Menueauswahl nach unten
if( Get_Key_Press( 1<<SW_MINUS ) || Get_Key_Rpt( 1<<SW_MINUS )) {
if (val > min_val) {
val--;
Key_Speedup_rpt(vrepeat); // beschleunigte Repeat-Funktion
}
else
if (cycle) {
val = max_val;
}
lcdGotoXY(posX, posY); // noch einmal lcd Position, sonst zum Teil + und - gleichzeitig, Anzeige verrutscht
Displ_Fnct(val); // geänderten Wert darstellen, je nach Menüpunkt
}
return(val);
}
 
/************************************************************************************/
/* */
/* Ändern der Werte mit Tasten +,- repetierend; (long)Entertaste und Anzeige */
/* z.B. für U-Offset, Batterie leer Eingabe ... */
/* */
/* Parameter: */
/* uint32_t val :zu ändernter Wert */
/* uint32_t min_val, max_val :min, max Grenze Wert ändern darf */
/* uint8_t pos :Darstellung Wert xPos auf LCD */
/* Displ_Fnct_t Displ_Fnct :Index um variable Display Funktion aufzurufen */
/* uint8_t vrepeat :beschleunigte Repeat-Funktion aus/ein */
/* uint32_t Change_Value(...) :Rückgabe geänderter Wert */
/* */
/************************************************************************************/
uint32_t Change_Value(uint32_t val, uint32_t min_val, uint32_t max_val, uint8_t pos, Displ_Fnct_t Displ_Fnct, \
uint8_t vrepeat)
{
lcdGotoXY(pos, ZLE_VAL); // Position Wert
Displ_Fnct(val); // initiale Wertdarstellung, je nach Menüpunkt
// bis Menueeingabe bestätigt oder zum vorherigen Menue
while( !Get_Key_Short( 1<<SW_ENTER ) && (pmenu[0] !='\0'))
{
val = Change_Value_plmi(val, min_val, max_val, pos, ZLE_VAL, Displ_Fnct, 0, vrepeat);
Long_Enter();
}
lcdClear();
return_m_pkt(strlen(pmenu)); // um bei Rücksprung auf ursprünglichen Menüpunkt zeigen oder Displ_Main_Disp()
return(val);
}
 
 
/**************************************************************/
/* */
/* LCD-Darstellungen der Menüs */
/* Zur Unterstützung der Auswahl werden einige Einstellungen */
/* sofort ausgeführt. Z.B.: Kontrast, Servo-Endausschlag */
/* */
/**************************************************************/
 
/************************************************************************************/
/* stellt eine String mittig auf Display dar */
/* Parameter: */
/* char *str : darzustellende Zeichenkette */
/* uint8_t zle : Display-Zeile */
/* */
/************************************************************************************/
void Displ_Str_mid(char *str, uint8_t zle)
{ int8_t x;
 
lcdGotoXY(0,zle);
for (x = 0; x < LCD_COLS; x++) lcdPutc(' '); // Zeile löschen
x = (LCD_COLS - strlen(str))/2; // Array-String mittig schreiben
lcdGotoXY(x,zle);
lcdPuts(str);
}
 
/************************************************************************************/
/* zeigt Menü- * Überschrift * auf erste Zeile mittig auf Display an */
/* Parameter: */
/* uint8_t message : index (MSG_) der darzustellenden Zeichenkette */
/* */
/************************************************************************************/
void Displ_Title(uint8_t message)
{ uint8_t l;
uint8_t x = 0;
 
l = strlen(Msg(message));
if ( LCD_COLS > l) x = (LCD_COLS - l)/2;
if (x > 1) {
lcdGotoXY(x - 2, 0);
lcdPuts("* ");
lcdPuts(Msg(message));
lcdPutc(' ');
}
else {
lcdGotoXY(0, 0);
lcdPutc('*');
lcdGotoXY(x, 0);
lcdPuts(Msg(message));
lcdGotoXY(LCD_COLS - 1, 0);
}
lcdPutc('*');
}
 
/************************************************************************************/
/* zeigt bei Programmstart Firmware- und DOGM-Version auf Display an */
/* */
/************************************************************************************/
void Displ_Version(void)
{
lcdGotoXY(0, 0);
lcdPuts(Msg(MSG_VERSION1));
if (dogm_vers == DOGM3V)
lcdPuts(Msg(MSG_UHW33V));
else
lcdPuts(Msg(MSG_UHW5V));
lcdPuts(Msg(MSG_VERSION2));
for ( uint8_t i=0; i<=30;i++)
_delay_ms(100);
lcdClear();
}
 
/************************************************************************************/
/* zeigt auszuwählenden/-gewählten Kanal und Frequenz auf Display an */
/* Parameter: */
/* uint32_t k :Index anzuzeigender Wert = Kanal + 0x30 als Char, */
/* unint32_t wegen Vereinheitlichung f. Funktionsaufrauf */
/* */
/************************************************************************************/
void Displ_Channels(uint32_t k)
{ char *channels[] = {"5740", "5760","5780", "5800", "5820", "5840", "5860"};
 
lcdPutc(k+0x30);
lcdPuts(": ");
lcdPuts(channels[k-1]);
lcdPuts("MHz");
}
 
/************************************************************************************/
/* zeigt Source AV1, AV2 oder Diversity zur Auswahl auf Display an */
/* Parameter: */
/* uint32_t q :Index anzuzeigender Wert, */
/* unint32_t wegen Vereinheitlichung f. Funktionsaufrauf */
/* */
/************************************************************************************/
void Displ_AV_Source(uint32_t q)
{ uint8_t av_src_table[] = {MSG_AV1, MSG_AV2, MSG_DIVERSITY};
 
Displ_Str_mid(Msg(av_src_table[q]), ZLE_VAL);
}
 
/************************************************************************************/
/* zeigt Tracking-Varianten zur Auswahl auf Display an */
/* Parameter: */
/* uint32_t q :Index anzuzeigender Wert, */
/* unint32_t wegen Vereinheitlichung f. Funktionsaufrauf */
/* */
/************************************************************************************/
void Displ_sel_Tracking(uint32_t q)
{ uint8_t track_sel_table[] = {MSG_OFF, MSG_TRACK_RSSI, MSG_TRACK_GPS, MSG_TRACK_MKCOCKPIT};
 
Displ_Str_mid(Msg(track_sel_table[q]), ZLE_VAL);
}
 
/************************************************************************************/
/* zeigt Senden der OSD-Daten Anforderung zur Auswahl auf Display an */
/* Parameter: */
/* uint32_t q :Index anzuzeigender Wert, */
/* unint32_t wegen Vereinheitlichung f. Funktionsaufrauf */
/* */
/************************************************************************************/
void Displ_track_TX(uint32_t q)
{ uint8_t track_TX_table[] = {MSG_OFF, MSG_TRACK_TX_ON};
 
Displ_Str_mid(Msg(track_TX_table[q]), ZLE_VAL);
}
 
/************************************************************************************/
/* zeigt einen max. 3-stelligen Integerwert auf Display an */
/* Parameter: */
/* uint32_t val :anzuzeigender Wert, */
/* unint32_t wegen Vereinheitlichung f. Funktionsaufrauf */
/* */
/************************************************************************************/
void Displ_Format_Int(uint32_t val)
{
lcdPuts(my_itoa(val, 0, 3, 0, 0));
}
 
/************************************************************************************/
/* zeigt den Kontrastwert auf Display an mit sofortiger Änderung */
/* Parameter: */
/* uint32_t val :anzuzeigender Wert, */
/* unint32_t wegen Vereinheitlichung f. Funktionsaufrauf */
/* */
/************************************************************************************/
void Displ_Set_Contrast(uint32_t val)
{
Displ_Format_Int(val);
lcdContrast(dogm_vers, val);
}
 
/************************************************************************************/
/* zeigt die Zeit zur Abschaltung der LCD-Hintergrundbeleuchtung an */
/* Parameter: */
/* uint32_t val :anzuzeigender Wert, */
/* unint32_t wegen Vereinheitlichung f. Funktionsaufrauf */
/* */
/************************************************************************************/
void Displ_Backgr_Light(uint32_t val)
{ char str[5];
uint8_t l;
l = strlen(Msg(MSG_LIGHT)); // etwas Aufwand um Zeilenende sauber zu löschen
switch(val) {
case BACKGR_LIGHT_MIN : l += strlen(Msg(MSG_LIGHT_OFF));
lcdPuts(Msg(MSG_LIGHT_OFF));
break;
case BACKGR_LIGHT_MAX : l += strlen(Msg(MSG_LIGHT_ON));
lcdPuts(Msg(MSG_LIGHT_ON));
break;
default : itoa (val * 10, str, 10);
lcdPutc(' ');
lcdPuts(str);
lcdPuts(Msg(MSG_SEC));
l += 1 + strlen(str) + strlen(Msg(MSG_SEC));
}
l = LCD_COLS - l;
for (uint8_t x = 0; x < l; x++) lcdPutc(' '); // Zeilenende löschen
}
 
/************************************************************************************/
/* zeigt ein oder aus zur Auswahl auf Display an */
/* Parameter: */
/* uint32_t val :0 = aus oder 1 = ein, */
/* unint32_t wegen Vereinheitlichung f. Funktionsaufrauf */
/* */
/************************************************************************************/
void Displ_Off_On(uint32_t val)
{
if (val == 0) lcdPuts(Msg(MSG_OFF)); else lcdPuts(Msg(MSG_ON));
}
 
/************************************************************************************/
/* zeigt Servoschritte zur Auswahl auf Display an */
/* Parameter: */
/* uint32_t val :0 = 255 oder 1 = 1023, */
/* unint32_t wegen Vereinheitlichung f. Funktionsaufrauf */
/* */
/************************************************************************************/
void Displ_Servo_Steps(uint32_t val)
{ uint8_t servo_step_table[] = {MSG_STEPS_255, MSG_STEPS_1023};
 
Displ_Str_mid(Msg(servo_step_table[val]), ZLE_VAL);
}
 
/************************************************************************************/
/* zeigt Servo-Anschlagposition links auf Display an */
/* mit sofortiger Wirkung auf Servo */
/* Parameter: */
/* uint32_t val :anzuzeigender Wert, */
/* unint32_t wegen Vereinheitlichung f. Funktionsaufrauf */
/* */
/************************************************************************************/
void Displ_Servo_Min(uint32_t val)
{ uint16_t steps = 0;
 
Displ_Format_Int(val);
servoSet_min(servo_nr, val); // Wert setzen damit nachfolgend die
if (servo[servo_nr].rev) steps = ServoSteps();
servoSetPosition(servo_nr, steps); // Änderung direkt am Servo sichtbar ist
}
 
/************************************************************************************/
/* zeigt Servo-Anschlagposition rechts auf Display an */
/* mit sofortiger Wirkung auf Servo */
/* Parameter: */
/* uint32_t val :anzuzeigender Wert, */
/* unint32_t wegen Vereinheitlichung f. Funktionsaufrauf */
/* */
/************************************************************************************/
void Displ_Servo_Max(uint32_t val)
{ uint16_t steps = ServoSteps();
 
Displ_Format_Int(val);
servoSet_max(servo_nr, val); // Wert setzen damit nachfolgend die
if (servo[servo_nr].rev) steps = 0;
servoSetPosition(servo_nr, steps); // Änderung direkt am Servo sichtbar ist
}
 
/************************************************************************************/
/* zeigt Servo-Anschlagposition Mitte auf Display an */
/* mit sofortiger Wirkung auf Servo */
/* Parameter: */
/* uint32_t val :anzuzeigender Wert, */
/* unint32_t wegen Vereinheitlichung f. Funktionsaufrauf */
/* */
/************************************************************************************/
void Displ_Servo_Mid(uint32_t val)
{ int16_t mid_val;
mid_val = val - ServoSteps()/2;
lcdPuts(my_itoa(mid_val, 1, 3, 0, 0));
servoSet_mid(servo_nr, val); // Wert setzen damit nachfolgend die
servoSetPosition(servo_nr, ServoSteps()/2);// Änderung direkt am Servo sichtbar ist
}
 
/************************************************************************************/
/* zeigt Baudrate für COM bei MKCockpit zur Auswahl auf Display an */
/* Parameter: */
/* uint32_t q :Index anzuzeigender Wert, */
/* unint32_t wegen Vereinheitlichung f. Funktionsaufrauf */
/* */
/************************************************************************************/
void Displ_Baudrate(uint32_t q)
{ char str[7];
 
ltoa(baud[q], str, 10);
Displ_Str_mid(str, ZLE_VAL);
}
 
/************************************************************************************/
/* zeigt Benutzung(Zeit) der beiden Empfänger auf Display an */
/* */
/************************************************************************************/
 
uint32_t TimeBase60(char *str, uint32_t time, uint8_t pos)
{ uint32_t tmp;
tmp = time % 60;
time /= 60;
for (int8_t i = pos; i >= (pos - 1); i--) {
str[i] = (tmp % 10) + '0';
tmp /= 10;
}
return(time);
}
 
void Displ_TimeHMS(uint32_t time)
{ char str[9];
 
time /= 4000; // Rechenfehler? Zähler aller 500µs
str[8] = '\0';
time = TimeBase60(str, time, 7);
time = TimeBase60(str, time, 4);
TimeBase60(str, time, 1);
str[2] = ':';
str[5] = ':';
lcdPuts(str);
}
 
void Displ_RX_Time(void)
{
lcdGotoXY(6, 1);
Displ_TimeHMS(rxcount0);
lcdGotoXY(6, 2);
Displ_TimeHMS(rxcount1);
}
 
/************************************************************************************/
/* zeigt den Marker in Hauptdarstellung auf selektierten RX an */
/* d Diversity, << fester RX */
/* Parameter: */
/* uint8_t p :x-Position des Markers */
/* uint8_t marker :Markerzeichen z.B.:'' oder 'd' oder 's' */
/* */
/************************************************************************************/
void Displ_AV_Mark(uint8_t p, char marker)
{
if (p < 2) {
lcdGotoXY(15,2 - p); // da p immer neue Position 0 oder 1
lcdPutc(' '); // bisherigen AVx-, Diversity-Marker löschen
lcdGotoXY(15,p + 1); // an neuer Positon
lcdPutc(marker); // übergebenes Markerzeichen darstellen
}
else { // falls beim Einschalten Diversity auf aktiv, keine Marker
lcdGotoXY(15,1);
lcdPutc(' ');
lcdGotoXY(15,2);
lcdPutc(' ');
}
}
 
/************************************************************************************/
/* Hauptanzeige unter Berücksichtigung von VBat */
/* */
/************************************************************************************/
void Displ_Main_Disp(void)
{ char marker;
 
lcdClear();
if (bat_low != 0) {
lcdClear();
Displ_Channels(channel);
lcdGotoXY(LCD_COLS - 1, 0);
lcdPuts("V\n1\n2");
if (av_source < DIVERSITY)
marker = MARKER_AV; // wird nur bei gesetzten Diversity überschrieben
else
marker = MARKER_RSSI; // nur Schönheit, damit man sofort Umschaltung sieht
Displ_AV_Mark(sw_avx, marker);
Displ_VBat(); // muss zuletzt stehen
}
else {
Displ_Str_mid(Msg(MSG_ACCU_LOW), 0);
}
}
 
 
 
/**************************************************************/
/* */
/* Menüs */
/* */
/**************************************************************/
 
/**************************/
/* */
/* Haupmenü */
/* */
/**************************/
void Menu_Main(void)
{ scr_menu_t scr_main_menu = {MSG_RETURN, MSG_AV_SOURCE, MSG_RX_CHANNEL, MSG_RSSI_CALIBR, MSG_LANGUAGE, MSG_SERVO_CALIBR, \
MSG_LCD , MSG_BATTERY, MSG_TRACKING, 0, MSG_GPS_DISPLAY};
 
strcpy(pmenu, "0");
Scroll_Menu(scr_main_menu, SCROLL_MAIN_MAX, m_pkt); // pmenu global
Jump_Menu(pmenu); //gewähltes Untermenü anspringen oder nur Return
}
 
/**************************/
/* */
/* AV-Quelle */
/* */
/**************************/
void Menu_AV_Source(void)
{ char marker;
uint32_t eep_val;
 
Displ_Title(MSG_AV_SOURCE);
eep_val = Change_Value(av_source, AV_SOURCE_MIN, AV_SOURCE_MAX, 3, Displ_AV_Source, C_REPEAT); // pmenu global
if (eep_val != av_source) {
cli();
av_source = eep_val;
eeprom_write_byte(&ep_av_source, av_source);
Double_Beep(DBEEPWR, DBEEPWRP);
sw_avx = Set_AV_Source(av_source);
if (pmenu[0] == '\0') { // sonst ist AV-Source marker im Hauptdisplay nicht aktuallisiert
if (av_source < DIVERSITY)
marker = MARKER_AV; // wird nur bei gesetzten Diversity überschrieben
else
marker = MARKER_RSSI; // nur Schönheit, damit man sofort Umschaltung sieht
Displ_AV_Mark(sw_avx, marker);// da erst jetzt die Variable für main_display geändert ist!
}
sei();
}
Jump_Menu(pmenu);
}
 
/**************************/
/* */
/* Kanal */
/* */
/**************************/
void Menu_RX_Channel(void)
{ uint32_t eep_val;
 
Displ_Title(MSG_RX_CHANNEL);
eep_val = Change_Value(channel, CHANNEL_MIN, CHANNEL_MAX, 3, Displ_Channels, C_REPEAT); // pmenu global
if ((eep_val != channel) || (eep_val != ch_stored)) { // oder Channel wurde im Hauptdisplay geändert
channel = eep_val;
ch_stored = eep_val;
eeprom_write_byte(&ep_channel, channel);
Double_Beep(DBEEPWR, DBEEPWRP);
Set_Channel(channel);
if (pmenu[0] == '\0') { // sonst ist channel im Hauptdisplay nicht aktuallisiert
lcdGotoXY(0,0);
Displ_Channels(channel); // da erst jetzt die Variable für main_display geändert ist!
}
}
Jump_Menu(pmenu);
}
 
/**************************/
/* */
/* RSSI */
/* */
/**************************/
void Menu_RSSI_Calibr(void)
{ uint8_t scr_sub_menu[3] = {MSG_RETURN, MSG_RSSI_MIN, MSG_RSSI_MAX};
 
Scroll_Menu(scr_sub_menu, 2, m_pkt); // pmenu global
Jump_Menu(pmenu);
}
 
void Menu_RSSI_min(void)
{ char str[20];
 
Displ_Title(MSG_RSSI_MIN);
strcpy(str, Msg(MSG_TX));
strcat(str, Msg(MSG_TX_OFF));
Displ_Str_mid(str, 1);
Displ_Str_mid(Msg(MSG_CONTINUE), 2);
if (Short_Enter()) { // pmenu global
RSSI_Min_Calibrate(pudbm);
pmenu[0] = '\0'; // zur Hauptdarstellung
Displ_Main_Disp(); // da erst jetzt die Variable für main_display geändert ist!
}
else
Jump_Menu(pmenu);
}
 
void Menu_RSSI_max(void)
{ char str[20];
 
Displ_Title(MSG_RSSI_MAX);
strcpy(str, Msg(MSG_TX));
strcat(str, Msg(MSG_TX_ON));
Displ_Str_mid(str, 1);
Displ_Str_mid(Msg(MSG_CONTINUE), 2);
if (Short_Enter()) { // pmenu global
RSSI_Max_Calibrate(pudbm);
pmenu[0] = '\0'; // zur Hauptdarstellung
Displ_Main_Disp(); // da erst jetzt die Variable für main_display geändert ist!
}
else
Jump_Menu(pmenu);
}
 
/**************************/
/* */
/* Sprache */
/* */
/**************************/
void Displ_Language(uint32_t i)
{ uint8_t lanuage_table[3] = {MSG_GERMAN, MSG_ENGLISH, MSG_FRENCH};
 
Displ_Str_mid(Msg(lanuage_table[i]), ZLE_VAL);
}
 
void Menu_Language(void)
{ uint32_t eep_val;
 
Displ_Title(MSG_LANGUAGE);
eep_val = Change_Value(language, GERMAN, LAST_LANG, 3, Displ_Language, C_REPEAT); // pmenu global
language = eeprom_read_byte(&ep_language); // damit bei Erstinbetriebnahme Sprache gespeichert wird NO_LANGUAGE
if (eep_val != language) {
language = eep_val;
eeprom_write_byte(&ep_language, language);
Double_Beep(DBEEPWR, DBEEPWRP);
}
Jump_Menu(pmenu);
}
 
/**************************/
/* */
/* Servos */
/* */
/**************************/
void Menu_Servo_Calibr(void)
{ uint8_t scr_sub_menu[4] = {MSG_RETURN, MSG_SERVO_STEPS, MSG_SERVO1, MSG_SERVO2};
 
Scroll_Menu(scr_sub_menu, 3, m_pkt); // pmenu global
Jump_Menu(pmenu);
}
 
void Servo_NewValues(uint8_t idx_presc)
{
for (uint8_t i = 0; i < SERVO_NUM_CHANNELS; i++) {
if (idx_presc == STEPS_255) { // Werte umrechnen für Prescaler = 256
servo[i].min /= 4;
servo[i].max /= 4;
servo[i].mid /= 4;
}
else { // Werte umrechnen für Prescaler = 64
servo[i].min *= 4;
servo[i].max *= 4;
servo[i].mid = (servo[i].mid + 1) * 4 - 1;
}
servoSet_min(i, servo[i].min);
servoSet_max(i, servo[i].max);
servoSet_mid(i, servo[i].mid);
eeprom_write_block(&servo[i],&ep_servo[i],sizeof(servo_t));
}
// Vorberechnung von ServoChannels[channel].duty
servoSetDefaultPos(); // Ausgangsstellung beider Servos
}
 
void Menu_Servo_Steps(void)
{ uint32_t eep_val;
 
Displ_Title(MSG_SERVO_STEPS);
lcdGotoXY(8, ZLE_VAL);
eep_val = Change_Value(sIdxSteps, STEPS_255, STEPS_1023, 5, Displ_Servo_Steps, C_REPEAT); // pmenu global
if (eep_val != sIdxSteps) {
cli();
sIdxSteps = eep_val;
eeprom_write_byte(&ep_sIdxSteps, sIdxSteps);
Servo_NewValues(sIdxSteps); // hier ist der neue Index anzugeben!
servoInit();
sei();
Double_Beep(DBEEPWR, DBEEPWRP);
}
Jump_Menu(pmenu);
}
 
void Menu_Servo1(void)
{ uint8_t scr_servo_menu[5] = {MSG_RETURN, MSG_SERVO1_REVERSE, MSG_CALIB1_LEFT, MSG_CALIB1_RIGHT, MSG_CALIB1_MIDDLE};
Scroll_Menu(scr_servo_menu, SCROLL_SERVO_MAX, m_pkt); // pmenu global
servo_nr = 0;
Jump_Menu(pmenu);
}
 
void Menu_Servo2(void)
{ uint8_t scr_servo_menu[5] = {MSG_RETURN, MSG_SERVO2_REVERSE, MSG_CALIB2_LEFT, MSG_CALIB2_RIGHT, MSG_CALIB2_MIDDLE};
Scroll_Menu(scr_servo_menu, SCROLL_SERVO_MAX, m_pkt); // pmenu global
servo_nr = 1;
Jump_Menu(pmenu);
}
 
uint8_t Servo_tmp_on(void)
{ uint8_t tmp_tracking = tracking;
 
tracking = 0; // Servopositionierung durch tracking abschalten
if (tracking == TRACKING_MIN) servoInit(); // falls aus, Servos einschalten
lcdGotoXY(0, 0); // lcd Cursor vorpositionieren
return(tmp_tracking);
}
 
void Servo_tmp_Original(uint8_t track)
{ uint16_t steps;
 
if (servo_nr == SERVO_PAN)
steps = ServoSteps()/2; // PAN auf Mittelstellung
else
steps = 0; // Tilt auf Endausschlag
servoSetPosition(servo_nr, steps); // Bei PAN auf ServoSteps/2 und bei Tilt auf 0 oder ServoSteps NICHT!!! reverse beachten
tracking = track; // ursprünglicher Wert Tracking aus, RSSI oder GPS
if (tracking == TRACKING_MIN) {
for (uint8_t i = 0; i < 2; i++)
_delay_ms(200); // sonst werden Impulse bereits vor erreichen der Servo-default-Stellung abgeschaltet
servoOff(); // Servos sind nur zum Tracking oder bei Kalibrierung eingeschaltet
}
Jump_Menu(pmenu);
}
 
void Menu_Servo_rev(void)
{ uint32_t eep_val;
uint8_t tmp_tracking;
 
tmp_tracking = Servo_tmp_on();
eep_val = Change_Value(servo[servo_nr].rev, 0, 1, 6, Displ_Off_On, C_REPEAT); // pmenu global; reverse gibt es nur 0=off, 1=on
if (eep_val != servo[servo_nr].rev) {
servo[servo_nr].rev = eep_val;
servoSet_rev(servo_nr, eep_val);
eeprom_write_block(&servo[servo_nr],&ep_servo[servo_nr],sizeof(servo_t));
Double_Beep(DBEEPWR, DBEEPWRP);
}
Servo_tmp_Original(tmp_tracking);
}
 
void Menu_Servo1_rev(void)
{
Displ_Title(MSG_SERVO1_REVERSE);
Menu_Servo_rev();
}
 
void Menu_Servo2_rev(void)
{
Displ_Title(MSG_SERVO2_REVERSE);
Menu_Servo_rev();
}
 
void Menu_Servo_left(void)
{ uint32_t eep_val;
uint8_t tmp_tracking;
 
tmp_tracking = Servo_tmp_on();
servoSetPosition(servo_nr, ServoSteps()); // Linkssanschlag um Kalibrierung am Servo zu sehen
eep_val = Change_Value(servo[servo_nr].max, servo_limit[sIdxSteps][LEFT].min, servo_limit[sIdxSteps][LEFT].max, 6, Displ_Servo_Max, V_REPEAT); // pmenu global
if (eep_val != servo[servo_nr].max) {
servo[servo_nr].max = eep_val;
eeprom_write_block(&servo[servo_nr],&ep_servo[servo_nr],sizeof(servo_t));
servoSet_mid(servo_nr, servo[servo_nr].mid); // Mittelposition muss sich bei Ausschlagsänderung verschieben
Double_Beep(DBEEPWR, DBEEPWRP);
}
Servo_tmp_Original(tmp_tracking);
}
 
void Menu_Servo1_left(void)
{
Displ_Title(MSG_CALIB1_LEFT);
Menu_Servo_left();
}
 
void Menu_Servo2_left(void)
{
Displ_Title(MSG_CALIB2_LEFT);
Menu_Servo_left();
}
 
void Menu_Servo_right(void)
{ uint32_t eep_val;
uint8_t tmp_tracking;
 
tmp_tracking = Servo_tmp_on();
servoSetPosition(servo_nr, 0); // Rechtsanschlag um Kalibrierung am Servo zu sehen
eep_val = Change_Value(servo[servo_nr].min, servo_limit[sIdxSteps][RIGHT].min, servo_limit[sIdxSteps][RIGHT].max, 6, Displ_Servo_Min, V_REPEAT); // pmenu global
if (eep_val != servo[servo_nr].min) {
servo[servo_nr].min = eep_val;
eeprom_write_block(&servo[servo_nr],&ep_servo[servo_nr],sizeof(servo_t));
servoSet_mid(servo_nr, servo[servo_nr].mid); // Mittelposition muss sich bei Ausschlagsänderung verschieben
Double_Beep(DBEEPWR, DBEEPWRP);
}
Servo_tmp_Original(tmp_tracking);
}
 
void Menu_Servo1_right(void)
{
Displ_Title(MSG_CALIB1_RIGHT);
Menu_Servo_right();
}
 
void Menu_Servo2_right(void)
{
Displ_Title(MSG_CALIB2_RIGHT);
Menu_Servo_right();
}
 
void Menu_Servo_middle(void)
{ uint32_t eep_val;
uint8_t tmp_tracking;
 
tmp_tracking = Servo_tmp_on();
servoSetPosition(servo_nr, ServoSteps()/2); // Mittelposition um Kalibrierung am Servo zu sehen
eep_val = Change_Value(servo[servo_nr].mid, servo_limit[sIdxSteps][MIDDLE].min, servo_limit[sIdxSteps][MIDDLE].max, 5, Displ_Servo_Mid, V_REPEAT); // pmenu global
if (eep_val != servo[servo_nr].mid) {
servo[servo_nr].mid = eep_val;
eeprom_write_block(&servo[servo_nr], &ep_servo[servo_nr], sizeof(servo_t));
Double_Beep(DBEEPWR, DBEEPWRP);
}
Servo_tmp_Original(tmp_tracking);
}
 
void Menu_Servo1_middle(void)
{
Displ_Title(MSG_CALIB1_MIDDLE);
Menu_Servo_middle();
}
 
void Menu_Servo2_middle(void)
{
Displ_Title(MSG_CALIB2_MIDDLE);
Menu_Servo_middle();
}
 
/**************************/
/* */
/* LCD */
/* */
/**************************/
void Menu_lcd(void)
{ uint8_t scr_sub_menu[3] = {MSG_RETURN, MSG_CONTRAST, MSG_BACKGR_LIGHT};
 
Scroll_Menu(scr_sub_menu, 2, m_pkt); // pmenu global
Jump_Menu(pmenu);
}
 
void Menu_lcd_Contrast(void)
{ uint32_t eep_val;
 
Displ_Title(MSG_LCD);
lcdGotoXY(2, ZLE_VAL);
lcdPuts(Msg(MSG_CONTRAST));
lcdPuts(": ");
eep_val = Change_Value(contrast, CONTRAST_MIN, CONTRAST_MAX, 11, Displ_Set_Contrast, C_REPEAT); // pmenu global
if (eep_val != contrast) {
contrast = eep_val;
eeprom_write_byte(&ep_contrast, contrast);
Double_Beep(DBEEPWR, DBEEPWRP);
}
Jump_Menu(pmenu);
}
 
void Menu_lcd_Backgr_Light(void)
{ uint32_t eep_val;
 
Displ_Title(MSG_BACKGR_LIGHT);
lcdGotoXY(0, ZLE_VAL);
lcdPuts(Msg(MSG_LIGHT));
eep_val = Change_Value(light_time, BACKGR_LIGHT_MIN, BACKGR_LIGHT_MAX, 6, Displ_Backgr_Light, V_REPEAT); // pmenu global
if (eep_val != light_time) {
light_time = eep_val;
eeprom_write_byte(&ep_light_time, light_time);
Double_Beep(DBEEPWR, DBEEPWRP);
if (light_time == BACKGR_LIGHT_MIN) lcdSet_BackgrLight_Off(); // Hintergrundbeleuchtung immer aus ==> sofort schalten
}
Jump_Menu(pmenu);
}
 
/**************************/
/* */
/* Batterie */
/* */
/**************************/
void Menu_Battery(void)
{ uint8_t scr_sub_menu[3] = {MSG_RETURN, MSG_U_SETUP, MSG_U_OFFSET};
 
Scroll_Menu(scr_sub_menu, 2, m_pkt); // pmenu global
Jump_Menu(pmenu);
}
 
void Menu_Low_U_Setup(void)
{ uint32_t eep_val;
 
Displ_Title(MSG_U_MIN);
eep_val = Change_Value(u_min, U_MIN_MIN, U_MIN_MAX, 4, Displ_U_2Nk, V_REPEAT); // pmenu global
if (eep_val != u_min) {
u_min = eep_val;
eeprom_write_dword(&ep_u_min, u_min);
hyst_u_min = u_min;
Double_Beep(DBEEPWR, DBEEPWRP);
}
Jump_Menu(pmenu);
}
 
void Menu_U_Offset(void)
{ uint32_t eep_val;
 
Displ_Title(MSG_U_OFFSET);
eep_val = Change_Value(u_offset, U_OFFSET_MIN, U_OFFSET_MAX, 4, Displ_U_2Nk, V_REPEAT); // pmenu global
if (eep_val != u_offset) {
u_offset = eep_val;
eeprom_write_byte(&ep_u_offset, u_offset);
Double_Beep(DBEEPWR, DBEEPWRP);
}
Jump_Menu(pmenu);
}
 
/**************************/
/* */
/* Antennennachführung */
/* */
/**************************/
void Menu_Tracking_Ant(void)
{ uint32_t eep_val;
 
Displ_Title(MSG_TRACKING);
eep_val = Change_Value(tracking, TRACKING_MIN, TRACKING_MAX, 3, Displ_sel_Tracking, C_REPEAT); // pmenu global
if (eep_val != tracking) {
cli();
tracking = eep_val;
sei();
eeprom_write_byte(&ep_tracking, tracking);
Double_Beep(DBEEPWR, DBEEPWRP);
USART_RX_Mode(tracking); // Unterschied Datenempfang GPS/MKCockpit
coldstart = 1;
rxcount0 = 0;
rxcount1 = 0;
servoSetDefaultPos(); // Ausgangsstellung beider Servos
if (tracking > TRACKING_MIN)
servoInit();
else {
for (uint8_t i = 0; i < 2; i++)
_delay_ms(200); // sonst wird Impuls bereits vor erreichen der Mittelstellung abgeschaltet
servoOff();
}
USART_Init_Baudrate();
}
Jump_Menu(pmenu);
}
 
/**************************/
/* Optionen */
/* Antennennachführung */
/* */
/**************************/
void Menu_Tracking_HYST(void)
{ uint32_t eep_val;
 
Displ_Title(MSG_HYSTERESE);
eep_val = Change_Value(track_hyst, TRACKING_HYST_MIN, TRACKING_HYST_MAX, 7, Displ_Format_Int, V_REPEAT); // pmenu gloabal
if (eep_val != track_hyst) {
track_hyst = eep_val;
eeprom_write_byte(&ep_track_hyst, track_hyst);
Double_Beep(DBEEPWR, DBEEPWRP);
}
Jump_Menu(pmenu);
}
 
void Menu_Tracking_TXOSD(void)
{ uint32_t eep_val;
 
Displ_Title(MSG_TRACK_TX_OSD_DATA);
eep_val = Change_Value(track_tx, 0, 1, 3, Displ_track_TX, C_REPEAT); // pmenu global; Senden gibt es nur 0=off, 1=on
if (eep_val != track_tx) {
track_tx = eep_val;
eeprom_write_byte(&ep_track_tx, track_tx);
Double_Beep(DBEEPWR, DBEEPWRP);
}
Jump_Menu(pmenu);
}
 
void Menu_Baudrate(void)
{ uint32_t eep_val;
 
Displ_Title(MSG_BAUDRATE);
eep_val = Change_Value(baudrate, BAUDRATE_MIN, BAUDRATE_MAX, 3, Displ_Baudrate, C_REPEAT); // pmenu global; Senden gibt es nur 0=off, 1=on
if (eep_val != baudrate) {
baudrate = eep_val;
eeprom_write_byte(&ep_baudrate, baudrate);
Double_Beep(DBEEPWR, DBEEPWRP);
USART_Init(baud[baudrate]);
}
Jump_Menu(pmenu);
}
 
void Menu_Tracking_Option(void)
{ // im Menü ist dies der gleiche Gliederungspunkt aber mit geänderter Auswahl
switch(tracking) {
case TRACKING_RSSI: Menu_Tracking_HYST();
break;
case TRACKING_GPS: Menu_Tracking_TXOSD();
break;
case TRACKING_MKCOCKPIT: Menu_Baudrate();
}
}
 
/**************************/
/* */
/* Anzeige GPS */
/* */
/**************************/
void Menu_GPS_Display(void)
{ uint8_t scr_sub_menu[5] = {MSG_RETURN, MSG_GPS_CALCULATE, MSG_GPS_CURRENT, MSG_GPS_HOME, MSG_RX_TIME};
 
Scroll_Menu(scr_sub_menu, 4, m_pkt); // pmenu global
Jump_Menu(pmenu);
}
 
void Menu_GPS_Display_FLAG(void) // ist Flag in tracking.c Tracking_GPS(void)
{ uint8_t slen;
slen = strlen(pmenu) - 1;
gps_display = pmenu[slen] - '0'; // char to byte 1 bis 3 im String enthalten
m_pkt = gps_display;
gps_disp_clear = 1; // damit Text "...keine Daten empf..." nach Datenempfang gelöscht wird
lcdPuts(Msg(MSG_GPS_NO_DATA));
if (Short_Enter()) // pmenu global
pmenu[slen] = '\0'; // Menüpunkt zurück
gps_display = GPS_DISP_NONE; // nach Tastaturabfrage keine Anzeige GPS, sondern normales Menü
Jump_Menu(pmenu);
}
 
void Menu_GPS_Displ_RX_Time(void)
{
Displ_Title(MSG_RX_TIME);
lcdGotoXY(0, 1);
lcdPuts(Msg(MSG_RX1));
lcdGotoXY(0, 2);
lcdPuts(Msg(MSG_RX2));
Displ_RX_Time();
gps_display = GPS_RX_COUNT;
m_pkt = gps_display;
if (Short_Enter()) // pmenu global
pmenu[strlen(pmenu) - 1] = '\0';// Menüpunkt zurück
gps_display = GPS_DISP_NONE; // nach Tastaturabfrage keine Anzeige GPS, sondern normales Menü
Jump_Menu(pmenu);
}
/NGVideo5_8/tags/v1.11/menue.h
0,0 → 1,89
 
/****************************************************************/
/* */
/* NG-Video 5,8GHz */
/* */
/* Copyright (C) 2011 - gebad */
/* */
/* This code is distributed under the GNU Public License */
/* which can be found at http://www.gnu.org/licenses/gpl.txt */
/* */
/****************************************************************/
 
#ifndef _MENUE_H_
#define _MENUE_H_
 
#define SCROLL_MAIN_MAX 8 // index array Scroll_Menu scr_main_menu[] = {....} Anzahl-1, da Beginn bei 0
#define SCROLL_SERVO_MAX 4 // index array Scroll_Menu scr_servo_menu[] = {....} Anzahl-1, da Beginn bei 0
 
/* bei Change_Value(....) */
#define ZLE_VAL 1 // DOGM Zeile des zu ändernten Wertes, einfache generelle bessere Gestaltung
 
#define C_REPEAT 0 // konstante repeat Geschwindigkeit
#define V_REPEAT 1 // sich ändernte repeat Geschwindigkeit
 
typedef struct
{
const char *menu_nr; // Stringzeiger auf Befehlsnamen
void (*fp)(void); // Zeiger auf auszuführende Funktion
} command_table_t;
void Menu_Main (void);
void Menu_AV_Source (void);
void Menu_RX_Channel (void);
void Menu_RSSI_Calibr (void);
void Menu_RSSI_min (void);
void Menu_RSSI_max (void);
void Menu_Language (void);
void Menu_Servo_Calibr (void);
void Menu_Servo_Steps (void);
void Menu_Servo1 (void);
void Menu_Servo2 (void);
void Menu_Servo1_rev (void);
void Menu_Servo1_left (void);
void Menu_Servo1_right (void);
void Menu_Servo1_middle (void);
void Menu_Servo2_rev (void);
void Menu_Servo2_left (void);
void Menu_Servo2_right (void);
void Menu_Servo2_middle (void);
void Menu_lcd (void);
void Menu_lcd_Contrast (void);
void Menu_lcd_Backgr_Light (void);
void Menu_Battery (void);
void Menu_Low_U_Setup (void);
void Menu_U_Offset (void);
void Menu_Tool (void);
void Menu_Tracking_Ant (void);
void Menu_Tracking_Option (void);
void Menu_GPS_Display (void);
void Menu_GPS_Display_FLAG (void);
void Menu_GPS_Displ_RX_Time (void);
 
char pmenu[5] = {"0"}; // Zuordnung Menü Programmgliederung zu hinterlegten Funktionen
uint8_t ch_stored; // Flag zur Speicherung, wenn Wert im Hauptdisplay geändert
uint8_t coldstart; // Flag erstmaliger MK-Start(Motore) nur nach GPS-Fix
 
void Displ_Main_Disp(void);
void Displ_AV_Mark(uint8_t p, char marker);
void Displ_Str_mid(char *str, uint8_t zle);
void Displ_RX_Time(void);
 
#define RIGHT 0 // Servopostionen, welche vom Einbau abhängig sind
#define LEFT 1
#define MIDDLE 2
 
typedef struct
{
uint16_t min; // entspricht Servopostionen, welche vom Einbau abhängig sind
uint16_t max;
} servo_limit_t;
 
servo_limit_t servo_limit[2][3] = {{{SERVO_I0_RIGHT_MIN, SERVO_I0_RIGHT_MAX},\
{SERVO_I0_LEFT_MIN, SERVO_I0_LEFT_MAX},\
{SERVO_I0_MIDDLE_MIN, SERVO_I0_MIDDLE_MAX}},\
{{SERVO_I1_RIGHT_MIN, SERVO_I1_RIGHT_MAX},\
{SERVO_I1_LEFT_MIN, SERVO_I1_LEFT_MAX},\
{SERVO_I1_MIDDLE_MIN, SERVO_I1_MIDDLE_MAX}}};
#endif /* _MENUE_H */
/NGVideo5_8/tags/v1.11/messages.c
0,0 → 1,223
 
/****************************************************************/
/* */
/* NG-Video 5,8GHz */
/* */
/* Copyright (C) 2011 - gebad */
/* */
/* This code is distributed under the GNU Public License */
/* which can be found at http://www.gnu.org/licenses/gpl.txt */
/* */
/* using */
/* http://www.avrfreaks.net/ */
/* index.php?name=PNphpBB2&file=viewtopic&t=71985&view=previous*/
/* */
/****************************************************************/
 
#include "messages.h"
 
PGM_P MessageTableGerman[LAST_NAT_MESSAGE+1] PROGMEM = {
MSG_TABLE(GERMAN, MSG_LANGUAGE),
MSG_TABLE(GERMAN, MSG_GERMAN),
MSG_TABLE(GERMAN, MSG_ENGLISH),
MSG_TABLE(GERMAN, MSG_FRENCH),
MSG_TABLE(GERMAN, MSG_RETURN),
MSG_TABLE(GERMAN, MSG_AV_SOURCE),
MSG_TABLE(GERMAN, MSG_RX_CHANNEL),
MSG_TABLE(GERMAN, MSG_RSSI_CALIBR),
MSG_TABLE(GERMAN, MSG_TX),
MSG_TABLE(GERMAN, MSG_TX_OFF),
MSG_TABLE(GERMAN, MSG_TX_ON),
MSG_TABLE(GERMAN, MSG_CONTINUE),
MSG_TABLE(GERMAN, MSG_CONTRAST),
MSG_TABLE(GERMAN, MSG_BACKGR_LIGHT),
MSG_TABLE(GERMAN, MSG_LIGHT),
MSG_TABLE(GERMAN, MSG_LIGHT_OFF),
MSG_TABLE(GERMAN, MSG_LIGHT_ON),
MSG_TABLE(GERMAN, MSG_SEC),
MSG_TABLE(GERMAN, MSG_BATTERY),
MSG_TABLE(GERMAN, MSG_U_MIN),
MSG_TABLE(GERMAN, MSG_U_SETUP),
MSG_TABLE(GERMAN, MSG_U_OFFSET),
MSG_TABLE(GERMAN, MSG_CALIBRATION),
MSG_TABLE(GERMAN, MSG_RUNNING),
MSG_TABLE(GERMAN, MSG_ERROR),
MSG_TABLE(GERMAN, MSG_TX_NOT),
MSG_TABLE(GERMAN, MSG_ACCU_LOW),
MSG_TABLE(GERMAN, MSG_SERVO_CALIBR),
MSG_TABLE(GERMAN, MSG_SERVO_STEPS),
MSG_TABLE(GERMAN, MSG_SERVO1_REVERSE),
MSG_TABLE(GERMAN, MSG_CALIB1_LEFT),
MSG_TABLE(GERMAN, MSG_CALIB1_RIGHT),
MSG_TABLE(GERMAN, MSG_CALIB1_MIDDLE),
MSG_TABLE(GERMAN, MSG_SERVO2_REVERSE),
MSG_TABLE(GERMAN, MSG_CALIB2_LEFT),
MSG_TABLE(GERMAN, MSG_CALIB2_RIGHT),
MSG_TABLE(GERMAN, MSG_CALIB2_MIDDLE),
MSG_TABLE(GERMAN, MSG_OFF),
MSG_TABLE(GERMAN, MSG_ON),
MSG_TABLE(GERMAN, MSG_TRACKING),
MSG_TABLE(GERMAN, MSG_TRACK_GPS),
MSG_TABLE(GERMAN, MSG_TRACK_TX_OSD_DATA),
MSG_TABLE(GERMAN, MSG_HYSTERESE),
MSG_TABLE(GERMAN, MSG_TRACK_TX_ON),
MSG_TABLE(GERMAN, MSG_GPS_DISPLAY),
MSG_TABLE(GERMAN, MSG_GPS_CALCULATE),
MSG_TABLE(GERMAN, MSG_GPS_CURRENT),
MSG_TABLE(GERMAN, MSG_GPS_HOME),
MSG_TABLE(GERMAN, MSG_GPS_NO_DATA),
MSG_TABLE(GERMAN, MSG_RX_TIME),
MSG_TABLE(GERMAN, MSG_COM),
MSG_TABLE(GERMAN, MSG_KOMMA),
MSG_TABLE(GERMAN, MSG_UHW33V),
};
 
PGM_P MessageTableEnglish[LAST_NAT_MESSAGE+1] PROGMEM = {
MSG_TABLE(ENGLISH, MSG_LANGUAGE),
MSG_TABLE(ENGLISH, MSG_GERMAN),
MSG_TABLE(ENGLISH, MSG_ENGLISH),
MSG_TABLE(ENGLISH, MSG_FRENCH),
MSG_TABLE(ENGLISH, MSG_RETURN),
MSG_TABLE(ENGLISH, MSG_AV_SOURCE),
MSG_TABLE(ENGLISH, MSG_RX_CHANNEL),
MSG_TABLE(ENGLISH, MSG_RSSI_CALIBR),
MSG_TABLE(ENGLISH, MSG_TX),
MSG_TABLE(ENGLISH, MSG_TX_OFF),
MSG_TABLE(ENGLISH, MSG_TX_ON),
MSG_TABLE(ENGLISH, MSG_CONTINUE),
MSG_TABLE(ENGLISH, MSG_CONTRAST),
MSG_TABLE(ENGLISH, MSG_BACKGR_LIGHT),
MSG_TABLE(ENGLISH, MSG_LIGHT),
MSG_TABLE(ENGLISH, MSG_LIGHT_OFF),
MSG_TABLE(ENGLISH, MSG_LIGHT_ON),
MSG_TABLE(ENGLISH, MSG_SEC),
MSG_TABLE(ENGLISH, MSG_BATTERY),
MSG_TABLE(ENGLISH, MSG_U_MIN),
MSG_TABLE(ENGLISH, MSG_U_SETUP),
MSG_TABLE(ENGLISH, MSG_U_OFFSET),
MSG_TABLE(ENGLISH, MSG_CALIBRATION),
MSG_TABLE(ENGLISH, MSG_RUNNING),
MSG_TABLE(ENGLISH, MSG_ERROR),
MSG_TABLE(ENGLISH, MSG_TX_NOT),
MSG_TABLE(ENGLISH, MSG_ACCU_LOW),
MSG_TABLE(ENGLISH, MSG_SERVO_CALIBR),
MSG_TABLE(ENGLISH, MSG_SERVO_STEPS),
MSG_TABLE(ENGLISH, MSG_SERVO1_REVERSE),
MSG_TABLE(ENGLISH, MSG_CALIB1_LEFT),
MSG_TABLE(ENGLISH, MSG_CALIB1_RIGHT),
MSG_TABLE(ENGLISH, MSG_CALIB1_MIDDLE),
MSG_TABLE(ENGLISH, MSG_SERVO2_REVERSE),
MSG_TABLE(ENGLISH, MSG_CALIB2_LEFT),
MSG_TABLE(ENGLISH, MSG_CALIB2_RIGHT),
MSG_TABLE(ENGLISH, MSG_CALIB2_MIDDLE),
MSG_TABLE(ENGLISH, MSG_OFF),
MSG_TABLE(ENGLISH, MSG_ON),
MSG_TABLE(ENGLISH, MSG_TRACKING),
MSG_TABLE(ENGLISH, MSG_TRACK_GPS),
MSG_TABLE(ENGLISH, MSG_TRACK_TX_OSD_DATA),
MSG_TABLE(ENGLISH, MSG_HYSTERESE),
MSG_TABLE(ENGLISH, MSG_TRACK_TX_ON),
MSG_TABLE(ENGLISH, MSG_GPS_DISPLAY),
MSG_TABLE(ENGLISH, MSG_GPS_CALCULATE),
MSG_TABLE(ENGLISH, MSG_GPS_CURRENT),
MSG_TABLE(ENGLISH, MSG_GPS_HOME),
MSG_TABLE(ENGLISH, MSG_GPS_NO_DATA),
MSG_TABLE(ENGLISH, MSG_RX_TIME),
MSG_TABLE(ENGLISH, MSG_COM),
MSG_TABLE(ENGLISH, MSG_KOMMA),
MSG_TABLE(ENGLISH, MSG_UHW33V),
};
 
PGM_P MessageTableFrench[LAST_NAT_MESSAGE+1] PROGMEM = {
MSG_TABLE(FRENCH, MSG_LANGUAGE),
MSG_TABLE(FRENCH, MSG_GERMAN),
MSG_TABLE(FRENCH, MSG_ENGLISH),
MSG_TABLE(FRENCH, MSG_FRENCH),
MSG_TABLE(FRENCH, MSG_RETURN),
MSG_TABLE(FRENCH, MSG_AV_SOURCE),
MSG_TABLE(FRENCH, MSG_RX_CHANNEL),
MSG_TABLE(FRENCH, MSG_RSSI_CALIBR),
MSG_TABLE(FRENCH, MSG_TX),
MSG_TABLE(FRENCH, MSG_TX_OFF),
MSG_TABLE(FRENCH, MSG_TX_ON),
MSG_TABLE(FRENCH, MSG_CONTINUE),
MSG_TABLE(FRENCH, MSG_CONTRAST),
MSG_TABLE(FRENCH, MSG_BACKGR_LIGHT),
MSG_TABLE(FRENCH, MSG_LIGHT),
MSG_TABLE(FRENCH, MSG_LIGHT_OFF),
MSG_TABLE(FRENCH, MSG_LIGHT_ON),
MSG_TABLE(FRENCH, MSG_SEC),
MSG_TABLE(FRENCH, MSG_BATTERY),
MSG_TABLE(FRENCH, MSG_U_MIN),
MSG_TABLE(FRENCH, MSG_U_SETUP),
MSG_TABLE(FRENCH, MSG_U_OFFSET),
MSG_TABLE(FRENCH, MSG_CALIBRATION),
MSG_TABLE(FRENCH, MSG_RUNNING),
MSG_TABLE(FRENCH, MSG_ERROR),
MSG_TABLE(FRENCH, MSG_TX_NOT),
MSG_TABLE(FRENCH, MSG_ACCU_LOW),
MSG_TABLE(FRENCH, MSG_SERVO_CALIBR),
MSG_TABLE(FRENCH, MSG_SERVO_STEPS),
MSG_TABLE(FRENCH, MSG_SERVO1_REVERSE),
MSG_TABLE(FRENCH, MSG_CALIB1_LEFT),
MSG_TABLE(FRENCH, MSG_CALIB1_RIGHT),
MSG_TABLE(FRENCH, MSG_CALIB1_MIDDLE),
MSG_TABLE(FRENCH, MSG_SERVO2_REVERSE),
MSG_TABLE(FRENCH, MSG_CALIB2_LEFT),
MSG_TABLE(FRENCH, MSG_CALIB2_RIGHT),
MSG_TABLE(FRENCH, MSG_CALIB2_MIDDLE),
MSG_TABLE(FRENCH, MSG_OFF),
MSG_TABLE(FRENCH, MSG_ON),
MSG_TABLE(FRENCH, MSG_TRACKING),
MSG_TABLE(FRENCH, MSG_TRACK_GPS),
MSG_TABLE(FRENCH, MSG_TRACK_TX_OSD_DATA),
MSG_TABLE(FRENCH, MSG_HYSTERESE),
MSG_TABLE(FRENCH, MSG_TRACK_TX_ON),
MSG_TABLE(FRENCH, MSG_GPS_DISPLAY),
MSG_TABLE(FRENCH, MSG_GPS_CALCULATE),
MSG_TABLE(FRENCH, MSG_GPS_CURRENT),
MSG_TABLE(FRENCH, MSG_GPS_HOME),
MSG_TABLE(FRENCH, MSG_GPS_NO_DATA),
MSG_TABLE(FRENCH, MSG_RX_TIME),
MSG_TABLE(FRENCH, MSG_COM),
MSG_TABLE(FRENCH, MSG_KOMMA),
MSG_TABLE(FRENCH, MSG_UHW33V),
};
 
PGM_P MessageTableInternational[MESSAGE_LAST_MESSAGE+1] PROGMEM = {
MSG_TABLE(INTERNAT, MSG_RSSI_MIN),
MSG_TABLE(INTERNAT, MSG_RSSI_MAX),
MSG_TABLE(INTERNAT, MSG_DIVERSITY),
MSG_TABLE(INTERNAT, MSG_LCD),
MSG_TABLE(INTERNAT, MSG_AV1),
MSG_TABLE(INTERNAT, MSG_AV2),
MSG_TABLE(INTERNAT, MSG_RX1),
MSG_TABLE(INTERNAT, MSG_RX2),
MSG_TABLE(INTERNAT, MSG_STEPS_255),
MSG_TABLE(INTERNAT, MSG_STEPS_1023),
MSG_TABLE(INTERNAT, MSG_SERVO1),
MSG_TABLE(INTERNAT, MSG_SERVO2),
MSG_TABLE(INTERNAT, MSG_TRACK_RSSI),
MSG_TABLE(INTERNAT, MSG_TRACK_MKCOCKPIT),
MSG_TABLE(INTERNAT, MSG_TRACK_SERVO_HYTERESE),
MSG_TABLE(INTERNAT, MSG_BAUDRATE),
MSG_TABLE(INTERNAT, MSG_UHW5V),
MSG_TABLE(INTERNAT, MSG_VERSION1),
MSG_TABLE(INTERNAT, MSG_VERSION2)
};
 
char* Msg(MessageType Message)
{ static char Str[LCD_LINES * LCD_COLS + 1];
 
if (Message > LAST_NAT_MESSAGE)
strcpy_P(Str, (const char*)( pgm_read_word( &(MessageTableInternational[Message - LAST_NAT_MESSAGE - 1]))));
else
switch (language) {
case ENGLISH: strcpy_P(Str, (const char*)( pgm_read_word( &(MessageTableEnglish[Message]))));
break;
case FRENCH : strcpy_P(Str, (const char*)( pgm_read_word( &(MessageTableFrench[Message]))));
break;
default: strcpy_P(Str, (const char*)( pgm_read_word( &(MessageTableGerman[Message]))));
}
return(Str);
}
/NGVideo5_8/tags/v1.11/messages.h
0,0 → 1,497
 
/****************************************************************/
/* */
/* NG-Video 5,8GHz */
/* */
/* Copyright (C) 2011 - gebad */
/* */
/* This code is distributed under the GNU Public License */
/* which can be found at http://www.gnu.org/licenses/gpl.txt */
/* */
/* using */
/* http://www.avrfreaks.net/ */
/* index.php?name=PNphpBB2&file=viewtopic&t=71985&view=previous*/
/* */
/****************************************************************/
 
#ifndef _MESSAGES_H_
#define _MESSAGES_H_
 
#include <avr/pgmspace.h>
 
/* International */
#define INTERNAT_RSSI_MIN "RSSI-Min"
#define INTERNAT_RSSI_MAX "RSSI-Max"
#define INTERNAT_DIVERSITY "Diversity"
#define INTERNAT_LCD "LCD"
#define INTERNAT_AV1 "AV1"
#define INTERNAT_AV2 "AV2"
#define INTERNAT_RX1 "1.RX:"
#define INTERNAT_RX2 "2.RX:"
#define INTERNAT_STEPS_255 "255"
#define INTERNAT_STEPS_1023 "1023"
#define INTERNAT_SERVO1 "Servo 1"
#define INTERNAT_SERVO2 "Servo 2"
#define INTERNAT_TRACK_RSSI "RSSI"
#define INTERNAT_TRACK_MKCOCKPIT "MK-Cockpit"
#define INTERNAT_TRACK_SERVO_HYTERESE "Servo-Hyster."
#define INTERNAT_BAUDRATE "Baudrate"
#define INTERNAT_UHW5V " 5V"
#define INTERNAT_VERSION1 "NG-Video 5.8GHz\nHW: "
#define INTERNAT_VERSION2 " M.Beck""FW: "VERSION " gebad"
 
#define GERMAN_LANGUAGE "Sprache"
#define GERMAN_GERMAN "Deutsch"
#define GERMAN_ENGLISH "Englisch"
#define GERMAN_FRENCH "Franz""\x94""sisch"
#define GERMAN_RETURN "Zur""\x81""ck"
#define GERMAN_AV_SOURCE "AV-Quelle"
#define GERMAN_RX_CHANNEL "RX-Kanal"
#define GERMAN_RSSI_CALIBR "RSSI-Kalibr."
#define GERMAN_TX "Bitte TX auf "
#define GERMAN_TX_OFF "AUS"
#define GERMAN_TX_ON "EIN"
#define GERMAN_CONTINUE "Weiter mit Enter"
#define GERMAN_CONTRAST "Kontrast"
#define GERMAN_BACKGR_LIGHT "LCD-Beleucht."
#define GERMAN_LIGHT "Licht:"
#define GERMAN_LIGHT_OFF " immer aus"
#define GERMAN_LIGHT_ON " immer ein"
#define GERMAN_SEC " Sek."
#define GERMAN_BATTERY "Batterie"
#define GERMAN_U_MIN "U-Min"
#define GERMAN_U_SETUP "Untersp.-Setup"
#define GERMAN_U_OFFSET "U-Offset"
#define GERMAN_CALIBRATION "Kalibrierung"
#define GERMAN_RUNNING "l""\x84""uft"
#define GERMAN_ERROR "Fehler!"
#define GERMAN_TX_NOT "Sender nicht "
#define GERMAN_ACCU_LOW " Akku\n entladen!"
#define GERMAN_SERVO_CALIBR "Servo-Kalibr."
#define GERMAN_SERVO_STEPS "Servo-Schritte"
#define GERMAN_CALIB "Kalib."
#define GERMAN_LEFT "links"
#define GERMAN_RIGHT "rechts"
#define GERMAN_MIDDLE "Mitte"
#define GERMAN_REVERSE "rev."
#define GERMAN_SERVO1_REVERSE INTERNAT_SERVO1 " " GERMAN_REVERSE
#define GERMAN_CALIB1_LEFT GERMAN_CALIB "1 " GERMAN_LEFT
#define GERMAN_CALIB1_RIGHT GERMAN_CALIB "1 " GERMAN_RIGHT
#define GERMAN_CALIB1_MIDDLE GERMAN_CALIB "1 " GERMAN_MIDDLE
#define GERMAN_SERVO2_REVERSE INTERNAT_SERVO2 " " GERMAN_REVERSE
#define GERMAN_CALIB2_LEFT GERMAN_CALIB "2 " GERMAN_LEFT
#define GERMAN_CALIB2_RIGHT GERMAN_CALIB "2 " GERMAN_RIGHT
#define GERMAN_CALIB2_MIDDLE GERMAN_CALIB "2 " GERMAN_MIDDLE
#define GERMAN_OFF "aus"
#define GERMAN_ON "ein"
#define GERMAN_TRACKING "Antenne nachf."
#define GERMAN_TRACK_GPS "GPS mit wi232"
#define GERMAN_TRACK_TX_OSD_DATA "TX OSD-Daten"
#define GERMAN_HYSTERESE "Hysterese"
#define GERMAN_TRACK_TX_ON "Sende Forderung"
#define GERMAN_GPS_DISPLAY "GPS-Anzeigen"
#define GERMAN_GPS_CALCULATE "berechn. Daten"
#define GERMAN_GPS_CURRENT "aktuelle Pos."
#define GERMAN_GPS_HOME "Startposition"
#define GERMAN_GPS_NO_DATA " Noch\n keine Daten\n empfangen!"
#define GERMAN_RX_TIME "RX-Zeit"
#define GERMAN_COM "Seriell COM"
#define GERMAN_KOMMA ","
#define GERMAN_UHW33V "3,3V"
 
#define ENGLISH_LANGUAGE "Language"
#define ENGLISH_GERMAN "German"
#define ENGLISH_ENGLISH "English"
#define ENGLISH_FRENCH "French"
#define ENGLISH_RETURN "Return"
#define ENGLISH_AV_SOURCE "AV-Source"
#define ENGLISH_RX_CHANNEL "RX-Channel"
#define ENGLISH_RSSI_CALIBR "RSSI-Calibr."
#define ENGLISH_TX "TX switch "
#define ENGLISH_TX_OFF "OFF"
#define ENGLISH_TX_ON "ON"
#define ENGLISH_CONTINUE "Continue Enter"
#define ENGLISH_CONTRAST "Contrast"
#define ENGLISH_BACKGR_LIGHT "Backgr. Light"
#define ENGLISH_LIGHT "Light:"
#define ENGLISH_LIGHT_OFF "always off"
#define ENGLISH_LIGHT_ON " always on"
#define ENGLISH_SEC " sec."
#define ENGLISH_BATTERY "Battery"
#define ENGLISH_U_MIN "U-Min"
#define ENGLISH_U_SETUP "Low voltage"
#define ENGLISH_U_OFFSET "U-Offset"
#define ENGLISH_CALIBRATION "Calibration"
#define ENGLISH_RUNNING "running"
#define ENGLISH_ERROR "Error!"
#define ENGLISH_TX_NOT "Transmitter not "
#define ENGLISH_ACCU_LOW " Accu\n low!"
#define ENGLISH_SERVO_CALIBR "Servo-Calibr."
#define ENGLISH_SERVO_STEPS "Servo-Steps"
#define ENGLISH_CALIB "Calib."
#define ENGLISH_LEFT "left"
#define ENGLISH_RIGHT "right"
#define ENGLISH_MIDDLE "middle"
#define ENGLISH_REVERSE "rev."
#define ENGLISH_SERVO1_REVERSE INTERNAT_SERVO1 " " ENGLISH_REVERSE
#define ENGLISH_CALIB1_LEFT ENGLISH_CALIB "1 " ENGLISH_LEFT
#define ENGLISH_CALIB1_RIGHT ENGLISH_CALIB "1 " ENGLISH_RIGHT
#define ENGLISH_CALIB1_MIDDLE ENGLISH_CALIB "1 " ENGLISH_MIDDLE
#define ENGLISH_SERVO2_REVERSE INTERNAT_SERVO2 " " ENGLISH_REVERSE
#define ENGLISH_CALIB2_LEFT ENGLISH_CALIB "2 " ENGLISH_LEFT
#define ENGLISH_CALIB2_RIGHT ENGLISH_CALIB "2 " ENGLISH_RIGHT
#define ENGLISH_CALIB2_MIDDLE ENGLISH_CALIB "2 " ENGLISH_MIDDLE
#define ENGLISH_OFF "off"
#define ENGLISH_ON "on "
#define ENGLISH_TRACKING "Tracking"
#define ENGLISH_TRACK_GPS "GPS with wi232"
#define ENGLISH_TRACK_TX_OSD_DATA "TX OSD-Data"
#define ENGLISH_HYSTERESE "Hysterese"
#define ENGLISH_TRACK_TX_ON "Transmit demand"
#define ENGLISH_GPS_DISPLAY "Display GPS"
#define ENGLISH_GPS_CALCULATE "calc. Data"
#define ENGLISH_GPS_CURRENT "current Pos."
#define ENGLISH_GPS_HOME "Homeposition"
#define ENGLISH_GPS_NO_DATA " Not yet\n Data\n received!"
#define ENGLISH_RX_TIME "RX-Time"
#define ENGLISH_COM "Seriell COM"
#define ENGLISH_KOMMA "."
#define ENGLISH_UHW33V "3.3V"
 
#define FRENCH_LANGUAGE "Langue"
#define FRENCH_GERMAN "Allemand"
#define FRENCH_ENGLISH "Anglais"
#define FRENCH_FRENCH "Fran""\x87""ais"
#define FRENCH_RETURN "Retour"
#define FRENCH_AV_SOURCE "AV-Source"
#define FRENCH_RX_CHANNEL "RX-Canal"
#define FRENCH_RSSI_CALIBR "RSSI-Calibr."
#define FRENCH_TX ""
#define FRENCH_TX_OFF "Eteindre Tx"
#define FRENCH_TX_ON "Allumer Tx"
#define FRENCH_CONTINUE "App. Enter"
#define FRENCH_CONTRAST "Contraste"
#define FRENCH_BACKGR_LIGHT "Retr. Ecl"
#define FRENCH_LIGHT "Eclai:"
#define FRENCH_LIGHT_OFF " Eteint"
#define FRENCH_LIGHT_ON " Tjrs ON"
#define FRENCH_SEC " Sec."
#define FRENCH_BATTERY "Batterie"
#define FRENCH_U_MIN "V-Min"
#define FRENCH_U_SETUP "Seuil Alarme"
#define FRENCH_U_OFFSET "V-Offset"
#define FRENCH_CALIBRATION "Calibration"
#define FRENCH_RUNNING "En cours"
#define FRENCH_ERROR "Erreur!"
#define FRENCH_TX_NOT "No Tx"
#define FRENCH_ACCU_LOW " Batterie\n faible!"
#define FRENCH_SERVO_CALIBR "Servo-Calibr"
#define FRENCH_SERVO_STEPS "Nbre de Pas"
#define FRENCH_CALIB "Calib."
#define FRENCH_LEFT "Gauche"
#define FRENCH_RIGHT "Droit"
#define FRENCH_MIDDLE "Milieu"
#define FRENCH_REVERSE "Inversion"
#define FRENCH_SERVO1_REVERSE "Invers. Servo1"
#define FRENCH_CALIB1_LEFT "Cal. Gauche"
#define FRENCH_CALIB1_RIGHT "Cal. Droite"
#define FRENCH_CALIB1_MIDDLE "Cal. Centre"
#define FRENCH_SERVO2_REVERSE "Invers. Servo2"
#define FRENCH_CALIB2_LEFT "Cal. Gauche"
#define FRENCH_CALIB2_RIGHT "Cal. Droite"
#define FRENCH_CALIB2_MIDDLE "Cal. Centre"
#define FRENCH_OFF "OFF"
#define FRENCH_ON "ON "
#define FRENCH_TRACKING "Tracking"
#define FRENCH_TRACK_GPS "GPS with wi232"
#define FRENCH_TRACK_TX_OSD_DATA "TX OSD-Data"
#define FRENCH_HYSTERESE "Hysteresis"
#define FRENCH_TRACK_TX_ON "Donn""\x82""e Transmie"
#define FRENCH_GPS_DISPLAY "Affichage GPS"
#define FRENCH_GPS_CALCULATE "Calcul GPS"
#define FRENCH_GPS_CURRENT "Pos. actuelle"
#define FRENCH_GPS_HOME "Homeposition"
#define FRENCH_GPS_NO_DATA " Aucune donn""\x82""e\n re""\x87""ue!"
#define FRENCH_RX_TIME "RX-Temps"
#define FRENCH_COM "COM. S""\x82""rie"
#define FRENCH_KOMMA "."
#define FRENCH_UHW33V "3.3V"
 
 
/* Languages */
#define GERMAN 0
#define ENGLISH 1
#define FRENCH 2
#define LAST_LANG 2
#define INTERNAT LAST_LANG + 1
#define NO_LANGUAGE 254 // für Sprachabfrage bei Erstinbetriebnahme NGVideo
 
/* Message languages */
#define MSG_LANGUAGE 0
#define MSG_GERMAN 1
#define MSG_ENGLISH 2
#define MSG_FRENCH 3
#define MSG_RETURN 4
#define MSG_AV_SOURCE 5
#define MSG_RX_CHANNEL 6
#define MSG_RSSI_CALIBR 7
#define MSG_TX 8
#define MSG_TX_OFF 9
#define MSG_TX_ON 10
#define MSG_CONTINUE 11
#define MSG_CONTRAST 12
#define MSG_BACKGR_LIGHT 13
#define MSG_LIGHT 14
#define MSG_LIGHT_OFF 15
#define MSG_LIGHT_ON 16
#define MSG_SEC 17
#define MSG_BATTERY 18
#define MSG_U_MIN 19
#define MSG_U_SETUP 20
#define MSG_U_OFFSET 21
#define MSG_CALIBRATION 22
#define MSG_RUNNING 23
#define MSG_ERROR 24
#define MSG_TX_NOT 25
#define MSG_ACCU_LOW 26
#define MSG_SERVO_CALIBR 27
#define MSG_SERVO_STEPS 28
#define MSG_SERVO1_REVERSE 29
#define MSG_CALIB1_LEFT 30
#define MSG_CALIB1_RIGHT 31
#define MSG_CALIB1_MIDDLE 32
#define MSG_SERVO2_REVERSE 33
#define MSG_CALIB2_LEFT 34
#define MSG_CALIB2_RIGHT 35
#define MSG_CALIB2_MIDDLE 36
#define MSG_OFF 37
#define MSG_ON 38
#define MSG_TRACKING 39
#define MSG_TRACK_GPS 40
#define MSG_TRACK_TX_OSD_DATA 41
#define MSG_HYSTERESE 42
#define MSG_TRACK_TX_ON 43
#define MSG_GPS_DISPLAY 44
#define MSG_GPS_CALCULATE 45
#define MSG_GPS_CURRENT 46
#define MSG_GPS_HOME 47
#define MSG_GPS_NO_DATA 48
#define MSG_RX_TIME 49
#define MSG_COM 50
#define MSG_KOMMA 51
#define MSG_UHW33V 52
#define LAST_NAT_MESSAGE 52
 
/* International */
#define MSG_RSSI_MIN 0 + LAST_NAT_MESSAGE + 1
#define MSG_RSSI_MAX 1 + LAST_NAT_MESSAGE + 1
#define MSG_DIVERSITY 2 + LAST_NAT_MESSAGE + 1
#define MSG_LCD 3 + LAST_NAT_MESSAGE + 1
#define MSG_AV1 4 + LAST_NAT_MESSAGE + 1
#define MSG_AV2 5 + LAST_NAT_MESSAGE + 1
#define MSG_RX1 6 + LAST_NAT_MESSAGE + 1
#define MSG_RX2 7 + LAST_NAT_MESSAGE + 1
#define MSG_STEPS_255 8 + LAST_NAT_MESSAGE + 1
#define MSG_STEPS_1023 9 + LAST_NAT_MESSAGE + 1
#define MSG_SERVO1 10 + LAST_NAT_MESSAGE + 1
#define MSG_SERVO2 11 + LAST_NAT_MESSAGE + 1
#define MSG_TRACK_RSSI 12 + LAST_NAT_MESSAGE + 1
#define MSG_TRACK_MKCOCKPIT 13 + LAST_NAT_MESSAGE + 1
#define MSG_TRACK_SERVO_HYTERESE 14 + LAST_NAT_MESSAGE + 1
#define MSG_BAUDRATE 15 + LAST_NAT_MESSAGE + 1
#define MSG_UHW5V 16 + LAST_NAT_MESSAGE + 1
#define MSG_VERSION1 17 + LAST_NAT_MESSAGE + 1
#define MSG_VERSION2 18 + LAST_NAT_MESSAGE + 1
#define MESSAGE_LAST_MESSAGE 18
 
#define MSG_TABLE(l,n) mt ## l ## _ ## n
#define MSG_STRING(l,n,s) \
const char mt ## l ## _ ## n [] PROGMEM = s ;
 
MSG_STRING(INTERNAT, MSG_RSSI_MIN, INTERNAT_RSSI_MIN)
MSG_STRING(INTERNAT, MSG_RSSI_MAX, INTERNAT_RSSI_MAX)
MSG_STRING(INTERNAT, MSG_DIVERSITY, INTERNAT_DIVERSITY)
MSG_STRING(INTERNAT, MSG_LCD, INTERNAT_LCD)
MSG_STRING(INTERNAT, MSG_AV1, INTERNAT_AV1)
MSG_STRING(INTERNAT, MSG_AV2, INTERNAT_AV2)
MSG_STRING(INTERNAT, MSG_RX1, INTERNAT_RX1)
MSG_STRING(INTERNAT, MSG_RX2, INTERNAT_RX2)
MSG_STRING(INTERNAT, MSG_STEPS_255, INTERNAT_STEPS_255)
MSG_STRING(INTERNAT, MSG_STEPS_1023, INTERNAT_STEPS_1023)
MSG_STRING(INTERNAT, MSG_SERVO1, INTERNAT_SERVO1)
MSG_STRING(INTERNAT, MSG_SERVO2, INTERNAT_SERVO2)
MSG_STRING(INTERNAT, MSG_TRACK_RSSI, INTERNAT_TRACK_RSSI)
MSG_STRING(INTERNAT, MSG_TRACK_MKCOCKPIT, INTERNAT_TRACK_MKCOCKPIT)
MSG_STRING(INTERNAT, MSG_TRACK_SERVO_HYTERESE, INTERNAT_TRACK_SERVO_HYTERESE)
MSG_STRING(INTERNAT, MSG_BAUDRATE, INTERNAT_BAUDRATE)
MSG_STRING(INTERNAT, MSG_UHW5V, INTERNAT_UHW5V)
MSG_STRING(INTERNAT, MSG_VERSION1, INTERNAT_VERSION1)
MSG_STRING(INTERNAT, MSG_VERSION2, INTERNAT_VERSION2)
 
MSG_STRING(GERMAN, MSG_LANGUAGE, GERMAN_LANGUAGE)
MSG_STRING(GERMAN, MSG_GERMAN, GERMAN_GERMAN)
MSG_STRING(GERMAN, MSG_ENGLISH, GERMAN_ENGLISH)
MSG_STRING(GERMAN, MSG_FRENCH, GERMAN_FRENCH)
MSG_STRING(GERMAN, MSG_RETURN, GERMAN_RETURN)
MSG_STRING(GERMAN, MSG_AV_SOURCE, GERMAN_AV_SOURCE)
MSG_STRING(GERMAN, MSG_RX_CHANNEL, GERMAN_RX_CHANNEL)
MSG_STRING(GERMAN, MSG_RSSI_CALIBR, GERMAN_RSSI_CALIBR)
MSG_STRING(GERMAN, MSG_TX, GERMAN_TX)
MSG_STRING(GERMAN, MSG_TX_OFF, GERMAN_TX_OFF)
MSG_STRING(GERMAN, MSG_TX_ON, GERMAN_TX_ON)
MSG_STRING(GERMAN, MSG_CONTINUE, GERMAN_CONTINUE)
MSG_STRING(GERMAN, MSG_CONTRAST, GERMAN_CONTRAST)
MSG_STRING(GERMAN, MSG_BACKGR_LIGHT, GERMAN_BACKGR_LIGHT)
MSG_STRING(GERMAN, MSG_LIGHT, GERMAN_LIGHT)
MSG_STRING(GERMAN, MSG_LIGHT_OFF, GERMAN_LIGHT_OFF)
MSG_STRING(GERMAN, MSG_LIGHT_ON, GERMAN_LIGHT_ON)
MSG_STRING(GERMAN, MSG_SEC, GERMAN_SEC)
MSG_STRING(GERMAN, MSG_BATTERY, GERMAN_BATTERY)
MSG_STRING(GERMAN, MSG_U_MIN, GERMAN_U_MIN)
MSG_STRING(GERMAN, MSG_U_SETUP, GERMAN_U_SETUP)
MSG_STRING(GERMAN, MSG_U_OFFSET, GERMAN_U_OFFSET)
MSG_STRING(GERMAN, MSG_CALIBRATION, GERMAN_CALIBRATION)
MSG_STRING(GERMAN, MSG_RUNNING, GERMAN_RUNNING)
MSG_STRING(GERMAN, MSG_ERROR, GERMAN_ERROR)
MSG_STRING(GERMAN, MSG_TX_NOT, GERMAN_TX_NOT)
MSG_STRING(GERMAN, MSG_ACCU_LOW, GERMAN_ACCU_LOW)
MSG_STRING(GERMAN, MSG_SERVO_CALIBR, GERMAN_SERVO_CALIBR)
MSG_STRING(GERMAN, MSG_SERVO_STEPS, GERMAN_SERVO_STEPS)
MSG_STRING(GERMAN, MSG_SERVO1_REVERSE, GERMAN_SERVO1_REVERSE)
MSG_STRING(GERMAN, MSG_CALIB1_LEFT, GERMAN_CALIB1_LEFT)
MSG_STRING(GERMAN, MSG_CALIB1_RIGHT, GERMAN_CALIB1_RIGHT)
MSG_STRING(GERMAN, MSG_CALIB1_MIDDLE, GERMAN_CALIB1_MIDDLE)
MSG_STRING(GERMAN, MSG_SERVO2_REVERSE, GERMAN_SERVO2_REVERSE)
MSG_STRING(GERMAN, MSG_CALIB2_LEFT, GERMAN_CALIB2_LEFT)
MSG_STRING(GERMAN, MSG_CALIB2_RIGHT, GERMAN_CALIB2_RIGHT)
MSG_STRING(GERMAN, MSG_CALIB2_MIDDLE, GERMAN_CALIB2_MIDDLE)
MSG_STRING(GERMAN, MSG_OFF, GERMAN_OFF)
MSG_STRING(GERMAN, MSG_ON, GERMAN_ON)
MSG_STRING(GERMAN, MSG_TRACKING, GERMAN_TRACKING)
MSG_STRING(GERMAN, MSG_TRACK_GPS, GERMAN_TRACK_GPS)
MSG_STRING(GERMAN, MSG_TRACK_TX_OSD_DATA, GERMAN_TRACK_TX_OSD_DATA)
MSG_STRING(GERMAN, MSG_HYSTERESE, GERMAN_HYSTERESE)
MSG_STRING(GERMAN, MSG_TRACK_TX_ON, GERMAN_TRACK_TX_ON)
MSG_STRING(GERMAN, MSG_GPS_DISPLAY, GERMAN_GPS_DISPLAY)
MSG_STRING(GERMAN, MSG_GPS_CALCULATE, GERMAN_GPS_CALCULATE)
MSG_STRING(GERMAN, MSG_GPS_CURRENT, GERMAN_GPS_CURRENT)
MSG_STRING(GERMAN, MSG_GPS_HOME, GERMAN_GPS_HOME)
MSG_STRING(GERMAN, MSG_GPS_NO_DATA, GERMAN_GPS_NO_DATA)
MSG_STRING(GERMAN, MSG_RX_TIME, GERMAN_RX_TIME)
MSG_STRING(GERMAN, MSG_COM, GERMAN_COM)
MSG_STRING(GERMAN, MSG_KOMMA, GERMAN_KOMMA)
MSG_STRING(GERMAN, MSG_UHW33V, GERMAN_UHW33V)
 
MSG_STRING(ENGLISH, MSG_LANGUAGE, ENGLISH_LANGUAGE)
MSG_STRING(ENGLISH, MSG_GERMAN, ENGLISH_GERMAN)
MSG_STRING(ENGLISH, MSG_ENGLISH, ENGLISH_ENGLISH)
MSG_STRING(ENGLISH, MSG_FRENCH, ENGLISH_FRENCH)
MSG_STRING(ENGLISH, MSG_RETURN, ENGLISH_RETURN)
MSG_STRING(ENGLISH, MSG_AV_SOURCE, ENGLISH_AV_SOURCE)
MSG_STRING(ENGLISH, MSG_RX_CHANNEL, ENGLISH_RX_CHANNEL)
MSG_STRING(ENGLISH, MSG_RSSI_CALIBR, ENGLISH_RSSI_CALIBR)
MSG_STRING(ENGLISH, MSG_TX, ENGLISH_TX)
MSG_STRING(ENGLISH, MSG_TX_OFF, ENGLISH_TX_OFF)
MSG_STRING(ENGLISH, MSG_TX_ON, ENGLISH_TX_ON)
MSG_STRING(ENGLISH, MSG_CONTINUE, ENGLISH_CONTINUE)
MSG_STRING(ENGLISH, MSG_CONTRAST, ENGLISH_CONTRAST)
MSG_STRING(ENGLISH, MSG_BACKGR_LIGHT, ENGLISH_BACKGR_LIGHT)
MSG_STRING(ENGLISH, MSG_LIGHT, ENGLISH_LIGHT)
MSG_STRING(ENGLISH, MSG_LIGHT_OFF, ENGLISH_LIGHT_OFF)
MSG_STRING(ENGLISH, MSG_LIGHT_ON, ENGLISH_LIGHT_ON)
MSG_STRING(ENGLISH, MSG_SEC, ENGLISH_SEC)
MSG_STRING(ENGLISH, MSG_BATTERY, ENGLISH_BATTERY)
MSG_STRING(ENGLISH, MSG_U_MIN, ENGLISH_U_MIN)
MSG_STRING(ENGLISH, MSG_U_SETUP, ENGLISH_U_SETUP)
MSG_STRING(ENGLISH, MSG_U_OFFSET, ENGLISH_U_OFFSET)
MSG_STRING(ENGLISH, MSG_CALIBRATION, ENGLISH_CALIBRATION)
MSG_STRING(ENGLISH, MSG_RUNNING, ENGLISH_RUNNING)
MSG_STRING(ENGLISH, MSG_ERROR, ENGLISH_ERROR)
MSG_STRING(ENGLISH, MSG_TX_NOT, ENGLISH_TX_NOT)
MSG_STRING(ENGLISH, MSG_ACCU_LOW, ENGLISH_ACCU_LOW)
MSG_STRING(ENGLISH, MSG_SERVO_CALIBR, ENGLISH_SERVO_CALIBR)
MSG_STRING(ENGLISH, MSG_SERVO_STEPS, ENGLISH_SERVO_STEPS)
MSG_STRING(ENGLISH, MSG_SERVO1_REVERSE, ENGLISH_SERVO1_REVERSE)
MSG_STRING(ENGLISH, MSG_CALIB1_LEFT, ENGLISH_CALIB1_LEFT)
MSG_STRING(ENGLISH, MSG_CALIB1_RIGHT, ENGLISH_CALIB1_RIGHT)
MSG_STRING(ENGLISH, MSG_CALIB1_MIDDLE, ENGLISH_CALIB1_MIDDLE)
MSG_STRING(ENGLISH, MSG_SERVO2_REVERSE, ENGLISH_SERVO2_REVERSE)
MSG_STRING(ENGLISH, MSG_CALIB2_LEFT, ENGLISH_CALIB2_LEFT)
MSG_STRING(ENGLISH, MSG_CALIB2_RIGHT, ENGLISH_CALIB2_RIGHT)
MSG_STRING(ENGLISH, MSG_CALIB2_MIDDLE, ENGLISH_CALIB2_MIDDLE)
MSG_STRING(ENGLISH, MSG_OFF, ENGLISH_OFF)
MSG_STRING(ENGLISH, MSG_ON, ENGLISH_ON)
MSG_STRING(ENGLISH, MSG_TRACKING, ENGLISH_TRACKING)
MSG_STRING(ENGLISH, MSG_TRACK_GPS, ENGLISH_TRACK_GPS)
MSG_STRING(ENGLISH, MSG_TRACK_TX_OSD_DATA, ENGLISH_TRACK_TX_OSD_DATA)
MSG_STRING(ENGLISH, MSG_HYSTERESE, ENGLISH_HYSTERESE)
MSG_STRING(ENGLISH, MSG_TRACK_TX_ON, ENGLISH_TRACK_TX_ON)
MSG_STRING(ENGLISH, MSG_GPS_DISPLAY, ENGLISH_GPS_DISPLAY)
MSG_STRING(ENGLISH, MSG_GPS_CALCULATE, ENGLISH_GPS_CALCULATE)
MSG_STRING(ENGLISH, MSG_GPS_CURRENT, ENGLISH_GPS_CURRENT)
MSG_STRING(ENGLISH, MSG_GPS_HOME, ENGLISH_GPS_HOME)
MSG_STRING(ENGLISH, MSG_GPS_NO_DATA, ENGLISH_GPS_NO_DATA)
MSG_STRING(ENGLISH, MSG_RX_TIME, ENGLISH_RX_TIME)
MSG_STRING(ENGLISH, MSG_COM, ENGLISH_COM)
MSG_STRING(ENGLISH, MSG_KOMMA, ENGLISH_KOMMA)
MSG_STRING(ENGLISH, MSG_UHW33V, ENGLISH_UHW33V)
 
MSG_STRING(FRENCH, MSG_LANGUAGE, FRENCH_LANGUAGE)
MSG_STRING(FRENCH, MSG_GERMAN, FRENCH_GERMAN)
MSG_STRING(FRENCH, MSG_ENGLISH, FRENCH_ENGLISH)
MSG_STRING(FRENCH, MSG_FRENCH, FRENCH_FRENCH)
MSG_STRING(FRENCH, MSG_RETURN, FRENCH_RETURN)
MSG_STRING(FRENCH, MSG_AV_SOURCE, FRENCH_AV_SOURCE)
MSG_STRING(FRENCH, MSG_RX_CHANNEL, FRENCH_RX_CHANNEL)
MSG_STRING(FRENCH, MSG_RSSI_CALIBR, FRENCH_RSSI_CALIBR)
MSG_STRING(FRENCH, MSG_TX, FRENCH_TX)
MSG_STRING(FRENCH, MSG_TX_OFF, FRENCH_TX_OFF)
MSG_STRING(FRENCH, MSG_TX_ON, FRENCH_TX_ON)
MSG_STRING(FRENCH, MSG_CONTINUE, FRENCH_CONTINUE)
MSG_STRING(FRENCH, MSG_CONTRAST, FRENCH_CONTRAST)
MSG_STRING(FRENCH, MSG_BACKGR_LIGHT, FRENCH_BACKGR_LIGHT)
MSG_STRING(FRENCH, MSG_LIGHT, FRENCH_LIGHT)
MSG_STRING(FRENCH, MSG_LIGHT_OFF, FRENCH_LIGHT_OFF)
MSG_STRING(FRENCH, MSG_LIGHT_ON, FRENCH_LIGHT_ON)
MSG_STRING(FRENCH, MSG_SEC, FRENCH_SEC)
MSG_STRING(FRENCH, MSG_BATTERY, FRENCH_BATTERY)
MSG_STRING(FRENCH, MSG_U_MIN, FRENCH_U_MIN)
MSG_STRING(FRENCH, MSG_U_SETUP, FRENCH_U_SETUP)
MSG_STRING(FRENCH, MSG_U_OFFSET, FRENCH_U_OFFSET)
MSG_STRING(FRENCH, MSG_CALIBRATION, FRENCH_CALIBRATION)
MSG_STRING(FRENCH, MSG_RUNNING, FRENCH_RUNNING)
MSG_STRING(FRENCH, MSG_ERROR, FRENCH_ERROR)
MSG_STRING(FRENCH, MSG_TX_NOT, FRENCH_TX_NOT)
MSG_STRING(FRENCH, MSG_ACCU_LOW, FRENCH_ACCU_LOW)
MSG_STRING(FRENCH, MSG_SERVO_CALIBR, FRENCH_SERVO_CALIBR)
MSG_STRING(FRENCH, MSG_SERVO_STEPS, FRENCH_SERVO_STEPS)
MSG_STRING(FRENCH, MSG_SERVO1_REVERSE, FRENCH_SERVO1_REVERSE)
MSG_STRING(FRENCH, MSG_CALIB1_LEFT, FRENCH_CALIB1_LEFT)
MSG_STRING(FRENCH, MSG_CALIB1_RIGHT, FRENCH_CALIB1_RIGHT)
MSG_STRING(FRENCH, MSG_CALIB1_MIDDLE, FRENCH_CALIB1_MIDDLE)
MSG_STRING(FRENCH, MSG_SERVO2_REVERSE, FRENCH_SERVO2_REVERSE)
MSG_STRING(FRENCH, MSG_CALIB2_LEFT, FRENCH_CALIB2_LEFT)
MSG_STRING(FRENCH, MSG_CALIB2_RIGHT, FRENCH_CALIB2_RIGHT)
MSG_STRING(FRENCH, MSG_CALIB2_MIDDLE, FRENCH_CALIB2_MIDDLE)
MSG_STRING(FRENCH, MSG_OFF, FRENCH_OFF)
MSG_STRING(FRENCH, MSG_ON, FRENCH_ON)
MSG_STRING(FRENCH, MSG_TRACKING, FRENCH_TRACKING)
MSG_STRING(FRENCH, MSG_TRACK_GPS, FRENCH_TRACK_GPS)
MSG_STRING(FRENCH, MSG_TRACK_TX_OSD_DATA, FRENCH_TRACK_TX_OSD_DATA)
MSG_STRING(FRENCH, MSG_HYSTERESE, FRENCH_HYSTERESE)
MSG_STRING(FRENCH, MSG_TRACK_TX_ON, FRENCH_TRACK_TX_ON)
MSG_STRING(FRENCH, MSG_GPS_DISPLAY, FRENCH_GPS_DISPLAY)
MSG_STRING(FRENCH, MSG_GPS_CALCULATE, FRENCH_GPS_CALCULATE)
MSG_STRING(FRENCH, MSG_GPS_CURRENT, FRENCH_GPS_CURRENT)
MSG_STRING(FRENCH, MSG_GPS_HOME, FRENCH_GPS_HOME)
MSG_STRING(FRENCH, MSG_GPS_NO_DATA, FRENCH_GPS_NO_DATA)
MSG_STRING(FRENCH, MSG_RX_TIME, FRENCH_RX_TIME)
MSG_STRING(FRENCH, MSG_COM, FRENCH_COM)
MSG_STRING(FRENCH, MSG_KOMMA, FRENCH_KOMMA)
MSG_STRING(FRENCH, MSG_UHW33V, FRENCH_UHW33V)
 
typedef uint16_t MessageType;
char* Msg(MessageType Message);
 
#endif /* _MESSAGES_H_ */
/NGVideo5_8/tags/v1.11/ngvideo.c
0,0 → 1,717
/****************************************************************/
/* */
/* NG-Video 5,8GHz */
/* */
/* Copyright (C) 2011 - gebad */
/* */
/* This code is distributed under the GNU Public License */
/* which can be found at http://www.gnu.org/licenses/gpl.txt */
/* */
/****************************************************************/
 
#include <avr/io.h>
#include <stdlib.h>
#include <avr/interrupt.h>
#include <avr/eeprom.h>
#include <util/delay.h>
 
#include "config.h"
#include "dogm.h"
#include "messages.h"
#include "ngvideo.h"
#include "menue.h"
#include "servo.h"
#include "tracking.c"
 
 
/************************************************************************************/
/* initialisiert den EEPROM mit default Werten, bzw. liest EEPROM gespeicherte */
/* Werte in gloabale Variablen. */
/* Parameter: */
/* uint8_t ep_reset :0 = zwangsweises Rückstetzen auf default-Werte */
/* */
/************************************************************************************/
void Init_EEPROM(uint8_t ep_reset)
{ char ver[sizeof(VERSION)];
uint8_t eep_init;
eep_init = eeprom_read_byte(&ep_eep_init);
eeprom_read_block(&ver, &ep_version, sizeof(VERSION));
_delay_ms(1);
 
if ((eep_init != EEP_INITB) || (ep_reset == 0) || strcmp(VERSION, ver))
{
// nur bei Erstinitialisierung DOGM auf default 3,3V setzen
if ((eep_init != EEP_INITB) || strcmp(VERSION, ver)){
eeprom_write_byte(&ep_eep_init, EEP_INITB);
eeprom_write_byte(&ep_dogm_vers, DOGM3V);
eeprom_write_byte(&ep_contrast, CONTRAST3V);
eeprom_write_block(&VERSION, &ep_version, sizeof(VERSION));
}
eeprom_write_byte(&ep_light_time, BACKGR_LIGHT_MAX);
eeprom_write_byte(&ep_u_offset, U_OFFSET);
eeprom_write_dword(&ep_u_min, U_MIN);
eeprom_write_byte(&ep_channel, CHANNEL);
eeprom_write_byte(&ep_av_source, AV_SOURCE);
eeprom_write_byte(&ep_language, NO_LANGUAGE);
eeprom_write_word(&ep_udbm_min, UDBM_MIN);
eeprom_write_word(&ep_udbm_max, UDBM_MAX);
eeprom_write_word(&ep_udbm_korr_1, UDBM_KORR_FA);
eeprom_write_word(&ep_udbm_korr_2, UDBM_KORR_FA);
eeprom_write_byte(&ep_sIdxSteps, STEPS_255);
eeprom_write_block(&servo[0],&ep_servo[0],sizeof(servo_t));
eeprom_write_block(&servo[1],&ep_servo[1],sizeof(servo_t));
eeprom_write_byte(&ep_tracking, TRACKING_MIN);
eeprom_write_byte(&ep_track_hyst, TRACKING_HYSTERESE);
eeprom_write_byte(&ep_track_tx, 0);
eeprom_write_byte(&ep_baudrate, BAUDRATE);
sIdxSteps = STEPS_255;
}
else
{
light_time = eeprom_read_byte(&ep_light_time);
u_offset = eeprom_read_byte(&ep_u_offset);
u_min = eeprom_read_dword(&ep_u_min);
channel = eeprom_read_byte(&ep_channel);
av_source = eeprom_read_byte(&ep_av_source);
language = eeprom_read_byte(&ep_language);
udbm_min = eeprom_read_word(&ep_udbm_min);
udbm_max = eeprom_read_word(&ep_udbm_max);
udbm_korr_1 = eeprom_read_word(&ep_udbm_korr_1);
udbm_korr_2 = eeprom_read_word(&ep_udbm_korr_2);
sIdxSteps = eeprom_read_byte(&ep_sIdxSteps);
eeprom_read_block(&servo[0],&ep_servo[0],sizeof(servo_t));
eeprom_read_block(&servo[1],&ep_servo[1],sizeof(servo_t));
tracking = eeprom_read_byte(&ep_tracking);
track_hyst = eeprom_read_byte(&ep_track_hyst);
track_tx = eeprom_read_byte(&ep_track_tx);
baudrate = eeprom_read_byte(&ep_baudrate);
}
dogm_vers = eeprom_read_byte(&ep_dogm_vers);
contrast = eeprom_read_byte(&ep_contrast);
hyst_u_min = u_min;
wudbm = RSSI_Calc_UdBm(pudbm); // Vergleichstabelle für dBm-Balken berechnen
sw_avx = av_source;
for (uint8_t i = 0; i < SERVO_NUM_CHANNELS; i++) {
servoSet_rev(i, servo[i].rev);
servoSet_min(i, servo[i].min);
servoSet_max(i, servo[i].max);
servoSet_mid(i, servo[i].mid);
}
// Vorberechnung von ServoChannels[channel].duty
servoSetDefaultPos(); // Ausgangsstellung beider Servos
coldstart = 1;
USART_Init_Baudrate();
USART_RX_Mode(tracking);
}
 
void servoSetDefaultPos(void)
{
servoSetPosition(SERVO_PAN, ServoSteps()/2); // Ausgangsstellung SERVO_PAN
servoSetPosition(SERVO_TILT, 0); // Ausgangsstellung SERVO_TILT
}
 
void USART_Init_Baudrate(void)
{
if (tracking == TRACKING_MKCOCKPIT)
USART_Init(baud[baudrate]);
else
USART_Init(baud[6]); //57600
}
 
/************************************************************************************/
/* setzt Flag für 3,3V oder 5V DOGM */
/* Parameter: */
/* uint8_t dogm :Version */
/* */
/************************************************************************************/
void Set_DOGM_Version(void)
{
if(dogm_vers == DOGM5V) {
dogm_vers = DOGM3V;
contrast = CONTRAST3V;
}
else {
dogm_vers = DOGM5V;
contrast = CONTRAST5V;
}
eeprom_write_byte(&ep_dogm_vers, dogm_vers);
eeprom_write_byte(&ep_contrast, contrast);
}
 
/************************************************************************************/
/* setzt den RX-Kanal von 1 bis 7 */
/* Parameter: */
/* uint8_t channel :Kanal */
/* */
/************************************************************************************/
void Set_Channel(uint8_t channel)
{ uint8_t tmp;
 
channel--;
tmp = channel & 0b00000111; // Kanal 1 bis 7 Werte 0 bis 6 setzen
PORTA |= tmp;
PORTB |= tmp;
tmp = channel | 0b11111000;
PORTA &= tmp;
PORTB &= tmp;
}
 
/************************************************************************************/
/* schaltet den MUX auf AV1 oder AV2 ohne Darstellung und en-/disabled Interrupt */
/* wird nur in main.c (Initialisierung) und Menü Sourceumschaltung eingesetzt */
/* deswegen cli() und sei() nur in Menu_AV_Source(void) */
/* Parameter: */
/* uint8_t src :0-AV1, 1-AV2 */
/* */
/************************************************************************************/
void SetMux0(void) {
SET_MUX_0;
mux_X = 0; // für Erkennung RX Zeitzähler
}
 
void SetMux1(void) {
SET_MUX_1;
mux_X = 1; // für Erkennung RX Zeitzähler
}
 
uint8_t Set_AV_Source(uint8_t src)
{
switch(src) {
case AV1: CLEAR_INT10; // Interrupt für Sync ausschalten
SetMux0();
break;
case AV2: CLEAR_INT10; // Interrupt für Sync ausschalten
SetMux1();
break;
case DIVERSITY: SET_INT10; // External Interrupt Mask Register ein
SetMux0();
break;
}
return(src);
}
 
 
/**************************************************************/
/* */
/* LCD-Backlight */
/* */
/**************************************************************/
 
void lcdSet_BackgrLight_Off(void)
{
backgr_light = OFF;
lcdBacklightOff();
}
 
void lcd_BackgrLight_On(void)
{ // ...&& (light_count < light_time)) ==> sonst wird Beleuchtung laufend wieder eingeschaltet
if ((backgr_light == OFF) && (light_time > BACKGR_LIGHT_MIN) && (light_count < light_time)) {
cli();
light_count = 0;
sei();
backgr_light = ON;
lcdBacklightOn();
}
}
 
void lcd_BackgrLight(void)
{
if (backgr_light == ON) { // nur wenn Beleuchtung an
if (light_time == BACKGR_LIGHT_MIN) // Hintergrundbeleuchtung immer aus?
lcdSet_BackgrLight_Off();
else
if (light_time < BACKGR_LIGHT_MAX) { // Hintergrundbeleuchtung immer an?
cli();
light_count++;
sei();
if (light_count >= light_time) lcdSet_BackgrLight_Off();
}
}
}
 
/**************************************************************/
/* */
/* ADC */
/* */
/* http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial */
/* */
/**************************************************************/
 
void ADC_Init(void)
{
uint16_t result;
ADMUX = (0<<REFS1) | (1<<REFS0); // AVcc als Referenz benutzen, da an AREF 4,8 V
ADCSRA = (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0); // Frequenzvorteiler Prescaler 128
ADCSRA |= (1<<ADEN); // ADC aktivieren
/* nach Aktivieren des ADC wird ein "Dummy-Readout" empfohlen, man liest
also einen Wert und verwirft diesen, um den ADC "warmlaufen zu lassen" */
ADCSRA |= (1<<ADSC); // eine ADC-Wandlung
while (ADCSRA & (1<<ADSC) ) {} // auf Abschluss der Konvertierung warten
/* ADCW muss einmal gelesen werden, sonst wird Ergebnis der nächsten
Wandlung nicht übernommen. */
result = ADCW;
}
 
/* ADC Einzelmessung */
uint16_t ADC_Read( uint8_t channel )
{
// Kanal waehlen, ohne andere Bits zu beeinflußen
ADMUX = (ADMUX & ~(0x1F)) | (channel & 0x1F);
ADCSRA |= (1<<ADSC); // eine Wandlung "single conversion"
while (ADCSRA & (1<<ADSC) ) {} // auf Abschluss der Konvertierung warten
return ADCW; // ADC auslesen und zurückgeben
}
 
/* ADC Mehrfachmessung mit Mittelwertbbildung */
uint16_t ADC_Read_Avg( uint8_t channel, uint16_t average )
{
uint32_t result = 0;
for (uint16_t i = 0; i < average; ++i ){
result += ADC_Read( channel );
_delay_ms(1);
}
return (uint16_t)( result / average );
}
 
 
/**************************************************************/
/* */
/* Beeper */
/* */
/**************************************************************/
 
void Beep(uint8_t time)
{
PORTB |= (1<<BEEPER);
// PINB &= ~(1<<BEEPER);
_delay_ms(time);
// PINB |= (1<<BEEPER);
PORTB &= ~(1<<BEEPER);
}
 
void Double_Beep(uint8_t time, uint8_t pause)
{
Beep(time);
_delay_ms(pause);
Beep(time);
}
 
/**************************************************************/
/* */
/* U-Batterie */
/* */
/**************************************************************/
 
/* Funktion zur Umwandlung einer vorzeichenbehafteten Integer
32-Bit "Festkomma-Zahl"(gedachtes Komma in Integer) in einen String
vereinfacht Variablenübergabe funktion change_value(uint32_t x),
kein printf, double oder float
siehe http://www.mikrocontroller.net/articles/Festkommaarithmetik
Vorz ==> 0 kein '-' trotz negativer Zahl, 1 wenn kein '-' bleibt Stelle leer
len max 11, Vorzeichen wird nicht mitgezählt aber Komma; Vorz 0 oder 1
Festkomma ==> Position der Kommastelle bei Integerwert
Nachkomma ==> angezeigte Nachkommastellen bei Festkomma
makefile derzeit somit auch ohne! Minimalistic printf version
Achtung: keine Fehlerprüfung! */
char* my_itoa(int32_t zahl, uint8_t Vorz, uint8_t len, uint8_t Festkomma, uint8_t Nachkomma)
{
int8_t i;
uint8_t neg = 0;
char Komma; // Sprachversion Deutsch ',' andere '.'
static char str[13];
 
Komma = Msg(MSG_KOMMA)[0]; // [0] nur als Char, sonst wäre es ein String
if( zahl < 0 ) { // ist die Zahl negativ?
zahl = -zahl;
neg = 1;
}
if (Vorz) str[0] = '0'; else len--;
str[len+1]='\0'; // String Terminator
if (Nachkomma > 0) Nachkomma++;
 
for(i=len; i>=Vorz; i--) {
if ((len - Festkomma == i) && (Festkomma > 0))
str[i]= Komma; // bei Bedarf Komma einfügen
else { // Integer-Dezimalumrechnung
str[i]=(zahl % 10) +'0'; // Modulo rechnen, dann den ASCII-Code von '0' addieren
zahl /= 10;
}
// festgelegt Festkomma aber verkleinern der Anzeige Mantisse
if ((Festkomma > 0) && (Festkomma >= Nachkomma) && (len - Festkomma + Nachkomma == i)) str[i]= '\0';
}
i=0;
while ((str[i+1] != Komma) && (i < len)) {
// Vorzeichen unmittelbar vor Zahl schreiben
if((Vorz) && (neg) && ((str[i+1] != '0') || (str[i+2] == Komma))) str[i] = '-';
// eine 0 vor Komma lassen
if(str[i] == '0') str[i++] = ' '; else break; // Vornullen entfernen
}
return(str);
}
 
// uint32_t u, da bei Displ_Fnct[fu_index](val) der größte Wert UBat gleich 32 Bit
void Displ_1Nk(uint32_t u)
{
// 0 kein Vorzeichen, 5 => 2 Ziffern vor Komma + 1 Komma + 2 Mantisse, Festkomma, eine Ziffer Nachkomma darstellen
lcdPuts(my_itoa(u,0,5,2,1));
}
 
void Displ_U_2Nk(uint32_t u)
{
lcdPuts(my_itoa(u,0,5,2,2));
lcdPutc('V');
}
 
// uint8_t beep_timer :Akku-leer-Beeper nur mit Task_0_1()-Intervalle bei Menü-Rücksprung
uint32_t U_Messen_cmp(uint8_t beep_timer)
{ uint32_t ubat;
static struct
{ uint8_t time;
uint8_t count;
} beep_low;
 
/* ubat = ((ADC_Read(VBAT) * Vref * (R104 + R103)) /(1024 * R103)) + UD10 (UD10 ist Offset)
Verhältniswert * 100 *8192 ( Verhältniswert = realer Korrekturwert;
mal 100 da alle Werte 2 Nachkommastellen berücksichtigt, aber ohne gerechnet wird
mal 8192 => ohne Bruch gerechnet aber dabei mehr Kommastellen berücksichtigt) */
ubat = (ADC_Read(VBAT) * (uint64_t)43504 + (uint64_t)u_offset * 8192)/ 8192;
if ( ubat <= hyst_u_min )
{
if (bat_low != 0) { // nicht laufend Display neu schreiben
hyst_u_min = u_min + 20; // 200mV Hysterese - beruhigt Anzeige
lcdClear();
lcdPuts(Msg(MSG_ACCU_LOW));
bat_low = 0;
Beep(BEEPBAT);
// da derzeit Fkt. aller 500ms aufgerufen, mit 2 Min Abstand beginnen
beep_low.time = BEEP_LOW_TIME;
beep_low.count = 0;
}
// Akku leer, in immer kürzeren Intervallen Beep
if ((beep_timer == 1) && (beep_low.count++ >= beep_low.time)){
Beep(BEEPBAT);
if (beep_low.time > 2)
beep_low.time /= 2;
beep_low.count = 0;
}
}
else {
if (hyst_u_min > u_min) { // falls Anzeige von Batterie leer
bat_low = 1; // und zurück geschaltet wird,
hyst_u_min = u_min; // dann Main_Disp wieder darstellen
Displ_Main_Disp();
}
}
return(ubat);
}
 
void Displ_VBat(void) // da u_offset globale Variable
{ uint32_t ubat;
ubat = U_Messen_cmp(ENABLE_BTIMER);
if (bat_low != 0) { // würde sonst Anzeige Akku leer überschreiben
lcdGotoXY(11, 0);
Displ_1Nk(ubat);
}
}
 
 
/**************************************************************/
/* */
/* RSSI */
/* */
/**************************************************************/
 
/* RSSI Werte Korrekturfaktor berechnen */
uint16_t RSSI_Calc_Korr(uint16_t u0, uint16_t u1)
{ uint16_t u_max;
 
// immer nur den kleineren Wert vergrößern
if (u0 < u1) {
udbm_korr_1 = (((uint32_t)u1 * UDBM_KORR_FA) / u0)+0.5; // nur mit Integer und 2 Nachkommastellen rechnen
udbm_korr_2 = UDBM_KORR_FA;
u_max = u1;
}
else {
udbm_korr_2 = (((uint32_t)u0 * UDBM_KORR_FA) / u1)+0.5; // nur mit Integer und 2 Nachkommastellen rechnen
udbm_korr_1 = UDBM_KORR_FA;
u_max = u0;
}
eeprom_write_word(&ep_udbm_korr_1, udbm_korr_1);
eeprom_write_word(&ep_udbm_korr_2, udbm_korr_2);
return(u_max);
}
 
void Displ_Calibr_Aktiv(void)
{
lcdClear();
Displ_Str_mid(Msg(MSG_CALIBRATION),0);
Displ_Str_mid(Msg(MSG_RUNNING),1);
}
 
void Displ_Error_TX(uint8_t message)
{
lcdClear();
Displ_Str_mid(Msg(MSG_ERROR),0);
Displ_Str_mid(Msg(MSG_TX_NOT),1);
Displ_Str_mid(Msg(message), 2);
for ( uint8_t i=0; i<=30;i++)
_delay_ms(100);
}
 
void RSSI_Min_Calibrate(uint16_t *pudbm)
{ uint16_t u0, u1;
 
Displ_Calibr_Aktiv();
u0 = ADC_Read_Avg(RSSI0, 1000); //1000 Wiederholungen mit
u1 = ADC_Read_Avg(RSSI1, 1000); //Mittelwertbildung
// Plausibilitätsprüfung ob Sender ausgeschaltet
if (u0 + u1 > 500) {
udbm_min = RSSI_Calc_Korr(u0, u1); // ist real die größere Spannung, aber der kleinere dbm Wert
eeprom_write_word(&ep_udbm_min, udbm_min);
Double_Beep(DBEEPWR, DBEEPWRP);
wudbm = RSSI_Calc_UdBm(pudbm);
}
else Displ_Error_TX(MSG_TX_OFF);
}
 
void RSSI_Max_Calibrate(uint16_t *pudbm)
{ uint16_t u0, u1;
 
Displ_Calibr_Aktiv();
u0 = ADC_Read_Avg(RSSI0, 1000); //1000 Wiederholungen mit
u1 = ADC_Read_Avg(RSSI1, 1000); //Mittelwertbildung
// Plausibilitätsprüfung ob Sender in der Nähe eingeschaltet
if (u0 + u1 < 400) {
udbm_max = RSSI_Calc_Korr(u0, u1); // ist real die kleinere Spannung, aber der größere dbm Wert
eeprom_write_word(&ep_udbm_max, udbm_max);
Double_Beep(DBEEPWR, DBEEPWRP);
wudbm = RSSI_Calc_UdBm(pudbm);
}
else Displ_Error_TX(MSG_TX_ON);
}
 
// Vergleichstabelle für RSSI-Bargraph berechnen, vermeidet laufend gleiche Berechnung
uint8_t RSSI_Calc_UdBm(uint16_t *pudbm)
{ uint8_t n;
// -15 um Ende dBm Skala sicher zu erreichen; ohne verfeinerten Bahrgraph war Wert -3
n = (udbm_min - udbm_max -15)/11;
for (uint8_t i = 0; i < 12; i++)
pudbm[i] = (udbm_min - i * n);
return(n / 5); // da 5 Pixel Breite pro Display-Zeichen; Anzeigebalken pro Pixel differenzieren
}
 
void Displ_RSSI_Bargraph(uint16_t *pudbm, uint8_t wudbm, uint16_t uadc)
{ char strBar[12];
uint8_t i;
int8_t lz = 11;
char b = 4;
// Balken zeichnen - udbm
for (i = 0; i < 12; i++) {
if ((b != ' ') && (uadc > pudbm[i])) {
b = ' ';
lz = i - 1;
}
strBar[i] = b;
}
if (lz >= 0) {
strBar[lz] = (pudbm[lz] - uadc) / wudbm ;// Anzeigebalken pro Pixel-"Breite" differenzieren
// bei Teilung 4 wäre richtig und keine Korr. erforderlich, so aber gleichmäßigerer Balkenverlauf
if (strBar[lz] > 4) strBar[lz] = 4;
}
for (i = 0; i < 12; i++)// lcdPuts (ist auch for) funktioniert hier nicht, da Char'\0' für Zeichen auch Stringende
lcdPutc(strBar[i]);
}
 
uint8_t RSSI_Diversity(uint8_t src, uint16_t *pudbm, uint8_t visible)
{ uint16_t u0, u1;
static uint8_t div_flag, ret_div_flag;
char marker;
 
u0 = (ADC_Read(RSSI0) * (uint32_t)udbm_korr_1)/UDBM_KORR_FA;
u1 = (ADC_Read(RSSI1) * (uint32_t)udbm_korr_2)/UDBM_KORR_FA;
// falls beide RX gleich gut/schlecht synchronisieren
// Achtung! Niedrigere Spannung - größere Feldstärke
if (src == DIVERSITY) {
if (u0 < u1) {
ret_div_flag = AV1;
if ((vscount0 == 255) && (vscount1 == 255)) SetMux0();
}
else {
ret_div_flag = AV2;
if ((vscount0 == 255) && (vscount1 == 255)) SetMux1();
}
}
else ret_div_flag = src; // sonst leerer Returnwert
if (visible) {
if (src == DIVERSITY) {
// Synchronisation vorrangig zur Feldstärke
if ((vsync0 != vsync1) && ((vscount0 & vscount1) < 255)) {
// ist nur zur Anzeige - Sync-MUX wird über Interrupt gesteuert
if (vsync0 == 0) {
div_flag = AV1;
}
else {
div_flag = AV2;
}
marker = MARKER_SYNC;
}
else {
div_flag = ret_div_flag;
marker = MARKER_RSSI;
}
}
else marker = MARKER_AV;
// wäre unschön - keine RSSI-Anzeige, aber Marker springt
if ((u0 > pudbm[0]) && (u1 > pudbm[0])) marker = ' ';
lcdGotoXY(2, 1);
Displ_RSSI_Bargraph(pudbm, wudbm, u0);
lcdGotoXY(2, 2);
Displ_RSSI_Bargraph(pudbm, wudbm, u1);
if (src == DIVERSITY) Displ_AV_Mark(div_flag, marker);
}
return(ret_div_flag);
}
 
/**************************************************************/
/* */
/* Diversity v-Synchronisation Interruptroutinen */
/* */
/**************************************************************/
 
/* Impulszähler für V-Synchronisation 0 und 1
wird durch Interrupt des jewiligen vSync einzeln zurückgesetzt */
ISR(TIMER2_OVF_vect)
{
TCNT2 = (int8_t)(int16_t)-(F_CPU / 64 * 500e-6); // preload
if (vscount0 < 255) ++vscount0; // Überlauf von vscount vermeiden
if (vscount1 < 255) ++vscount1; // Überlauf von vscount vermeiden
if (rx_timeout < RX_TIME_OLD) ++rx_timeout; // veranlasst bei GPS-Tracking MK Datensatz senden
if ((tracking == TRACKING_GPS) && (MK_Motor_run)) { // MK-Motoren müssen laufen
if (mux_X)
rxcount1++; // kein Test auf Überlauf ==> Counter groß genug - bis Stunden
else
rxcount0++;
}
}
 
/* Messung von Impulsabstand v-Synchronisation 0
Zur Vermeidung von Bildstörunen erfolgt MUX-Umschaltung in Bildaustastung */
ISR(INT0_vect)
{
if ((vscount0 >= 79) && (vscount0 <= 81))
vsync0 = 0;
else {
vsync0 = 1;
if (vsync1 == 0)
SetMux1();
}
if (vsync0 == vsync1) { //nur wenn vSynchronisation gleich gut/schlecht ist greift RSSI
if (sw_avx == AV1) {
SetMux0();
}
else
SetMux1();
}
vscount0 = 0;
}
 
/* Messung von Impulsabstand v-Synchronisation 1
Zur Vermeidung von Bildstörunen erfolgt MUX-Umschaltung in Bildaustastung */
ISR(INT1_vect)
{
if ((vscount1 >= 79) && (vscount1 <= 81))
vsync1 = 0;
else {
vsync1 = 1;
if (vsync0 == 0)
SetMux0();
}
if (vsync0 == vsync1) { //nur wenn vSynchronisation gleich gut/schlecht ist greift RSSI
if (sw_avx == AV1) {
SetMux0();
}
else
SetMux1();
}
vscount1 = 0;
}
 
/**************************************************************/
/* */
/* Tasks */
/* ermöglicht unterschiedliche Zeiten f. UBat, Sync... */
/* */
/**************************************************************/
 
void Task_0_1(void)
{
if (task_timer0_1) {
cli();
task_timer0_1 = 0;
sei();
Displ_VBat();
}
}
 
void Task_0_2(void)
{
if (task_timer0_2) {
cli();
task_timer0_2 = 0;
sei();
sw_avx = RSSI_Diversity(av_source, pudbm, bat_low);
}
}
 
void Task_0_3(void)
{
if (task_timer0_3) {
cli();
task_timer0_3 = 0;
sei();
sw_avx = RSSI_Diversity(av_source, pudbm, 0);
if (tracking == TRACKING_MKCOCKPIT) Tracking_MKCockpit();
}
}
 
void Task_0_4(void)
{
if (task_timer0_4) {
cli();
task_timer0_4 = 0;
sei();
if (tracking == TRACKING_GPS) Tracking_GPS();
if (gps_display == GPS_RX_COUNT) Displ_RX_Time(); // aktualisieren der Empfängerzeiten
}
}
 
void Task_0_5(void) // Nur für Tasten-Beschleunigung/-Wiederholrate! Hintergrund: Rücksetzung.
{ // Hintergrund: Rücksetzung. Beginnt nach jeden Tastendruck neu zu zählen.
lcd_BackgrLight_On(); // muss bei beliebiger Taste sofort eingeschaltet werden
if (task_timer0_5) {
cli();
task_timer0_5 = 0;
sei();
lcd_BackgrLight();
}
}
 
void Tasks_unvisible(void)
{
Task_0_3();
Task_0_4();
Task_0_5();
if (tracking == TRACKING_RSSI) Tracking_RSSI();
}
/NGVideo5_8/tags/v1.11/ngvideo.h
0,0 → 1,141
 
/****************************************************************/
/* */
/* NG-Video 5,8GHz */
/* */
/* Copyright (C) 2011 - gebad */
/* */
/* This code is distributed under the GNU Public License */
/* which can be found at http://www.gnu.org/licenses/gpl.txt */
/* */
/****************************************************************/
 
#ifndef SETTING_H_
#define SETTING_H_
 
/* Indexwerte für av_source bzw. zur Auswertung von av_source */
#define AV1 0
#define AV2 1
#define DIVERSITY 2
 
#define MARKER_SELECT 0xfc // 0xfc enspricht '>>' Menue-Marker
#define MARKER_AV 0xfb // 0xfb enspricht '<<' Diversity AV-Marker
#define MARKER_RSSI 'd' // Diversity, wenn RX umschaltet mittels RSSI-Wert
#define MARKER_SYNC 's' // Diversity, wenn RX umschaltet auf Grund der Bildsynchronisation
 
#define SET_MUX_0 PORTA &= ~(1<<MUX_IN); // MUX SxA enabled
#define SET_MUX_1 PORTA |= (1<<MUX_IN); // MUX SxB enabled
#define CLEAR_INT10 EIMSK &= ~((1<<INT1) | (1<<INT0)); // Interrupt für Sync ausschalten
#define SET_INT10 EIMSK |= (1<<INT1) | (1<<INT0); // External Interrupt Mask Register ein
 
/* Beep Verzögerungszeitein */
#define DBEEPVERS 2 // Beep on nach Versionsanzeige
#define DBEEPVERSP 30 // Beep Pause nach Versionsanzeige
#define BEEPENTER 1 // Beep on Enter kurz Scroll_Menu() und Select_Menu()
#define DBEEPWR 4 // Beep on geänderte Werte ROM schreiben
#define DBEEPWRP 30 // Beep Pause geänderte Werte ROM schreiben
#define BEEPBAT 20 // Beep on bei Akku low
#define BEEP_LOW_TIME 240 // TIMER0_1 aller 500ms aufgerufen, BeepIntervall Akku leer mit 2 Min Abstand beginnen
 
#define ENABLE_BTIMER 1 // damit Intervall Beeper für Akku leer mit TIMER0_1 gesteuert wird
#define DISABLE_BTIMER 0
 
#define GPS_DISP_NONE 0 // Anzeigen bei Antennennachführung per WI232 und GPS
#define GPS_DISP_CALC 1
#define GPS_DISP_CURRENT 2
#define GPS_DISP_HOME 3
#define GPS_RX_COUNT 4
 
#define BAUDRATE 5 // für Antennennachführung mittels MKCockpit
#define BAUDRATE_MIN 0
#define BAUDRATE_MAX 6
 
#define POLOLU_CMD 2
 
#define OFF 0
#define ON 1
 
#define EEPROM __attribute__ ((section(".eeprom")))
 
uint32_t baud[8] = {4800, 7200, 9600, 14400, 19200, 38400, 57600};
 
typedef struct {
uint8_t rev;
uint16_t min;
uint16_t max;
uint16_t mid;
} servo_t;
 
/**************************************************************/
/* */
/* EEPROM */
/* */
/**************************************************************/
static uint8_t ep_eep_init EEPROM;
static char ep_version[sizeof(VERSION)] EEPROM;
static uint8_t ep_dogm_vers EEPROM;
static uint8_t ep_contrast EEPROM;
static uint8_t ep_light_time EEPROM;
static uint8_t ep_u_offset EEPROM;
static uint32_t ep_u_min EEPROM;
static uint8_t ep_channel EEPROM;
static uint8_t ep_av_source EEPROM;
static uint8_t ep_language EEPROM;
static uint16_t ep_udbm_min EEPROM;
static uint16_t ep_udbm_max EEPROM;
static uint16_t ep_udbm_korr_1 EEPROM;
static uint16_t ep_udbm_korr_2 EEPROM;
static uint8_t ep_sIdxSteps EEPROM;
static servo_t ep_servo[SERVO_NUM_CHANNELS][sizeof(servo_t)] EEPROM;
static uint8_t ep_tracking EEPROM;
static uint8_t ep_track_hyst EEPROM;
static uint8_t ep_track_tx EEPROM;
static uint8_t ep_baudrate EEPROM;
 
uint8_t dogm_vers;
uint8_t contrast;
uint8_t light_time = BACKGR_LIGHT_MAX;
uint8_t backgr_light = OFF;
uint8_t u_offset = U_OFFSET;
uint32_t u_min = U_MIN;
uint8_t channel = CHANNEL;
uint8_t av_source = AV_SOURCE;
uint8_t language = NO_LANGUAGE;
uint16_t udbm_min = UDBM_MIN;
uint16_t udbm_max = UDBM_MAX;
uint16_t udbm_korr_1 = UDBM_KORR_FA;
uint16_t udbm_korr_2 = UDBM_KORR_FA;
uint32_t hyst_u_min;
servo_t servo[SERVO_NUM_CHANNELS] = {{SERVO_REV, SERVO_I0_RIGHT, SERVO_I0_LEFT, SERVO_I0_MIDDLE},\
{SERVO_REV, SERVO_I0_RIGHT, SERVO_I0_LEFT, SERVO_I0_MIDDLE}};
uint8_t tracking = TRACKING_MIN;
uint8_t track_hyst = TRACKING_HYSTERESE;
uint8_t track_tx = 0;
uint8_t baudrate = BAUDRATE;
uint8_t gps_display = 0;
uint8_t gps_disp_clear;
 
uint8_t RSSI_Calc_UdBm(uint16_t *pudbm);
uint8_t Set_AV_Source(uint8_t src);
 
uint16_t udbm[12]; // RSSI-Bargraph
uint16_t* pudbm = udbm;
uint8_t wudbm; // Differenz/Abstand benachbarter udbm[i] für differenzierteren Bargraphen
uint8_t bat_low = 1;
uint8_t sw_avx; // steuert über Set_AV_Source() oder rssi_diversity(av_source) Marker-Position und RX-Umschaltung
uint8_t mux_X; // berücksichtigt Schaltung auf Grund Synchronisation und RSSI (sw_avx meist RSSI) RX-Zählung
uint8_t MK_Motor_run = 0; // Flag für RX Time-Counter Start/Stop
 
volatile uint8_t vsync0;
volatile uint8_t vsync1;
volatile uint8_t vscount0;
volatile uint8_t vscount1;
volatile uint32_t rxcount0 = 0;
volatile uint32_t rxcount1 = 0;
 
uint16_t ADC_Read( uint8_t channel );
void servoSetDefaultPos(void);
void USART_Init_Baudrate(void);
char* my_itoa(int32_t zahl, uint8_t Vorz, uint8_t len, uint8_t Festkomma, uint8_t Nachkomma);
 
#endif /* SETTING_H_ */
/NGVideo5_8/tags/v1.11/servo.c
0,0 → 1,180
 
/********************************************************************/
/* */
/* NG-Video 5,8GHz */
/* */
/* Copyright (C) 2011 - gebad */
/* */
/* This code is distributed under the GNU Public License */
/* which can be found at http://www.gnu.org/licenses/gpl.txt */
/* */
/* using */
/*! \file servo.c \brief Interrupt-driven RC Servo function library.*/
/* */
/*File Name : 'servo.c' */
/*Title : Interrupt-driven RC Servo function library */
/*Author : Pascal Stang - Copyright (C) 2002 */
/*Created : 7/31/2002 */
/*Revised : 8/02/2002 */
/*Version : 1.0 */
/*Target MCU : Atmel AVR Series */
/*Editor Tabs : 4 */
/* */
/*This code is distributed under the GNU Public License */
/* which can be found at http://www.gnu.org/licenses/gpl.txt */
/* */
/********************************************************************/
 
#include <avr/interrupt.h>
#include <avr/io.h>
 
#include "servo.h"
#include "config.h"
 
// Global variables
uint16_t ServoPosTics;
uint16_t ServoPeriodTics;
 
// servo channel registers
ServoChannelType ServoChannels[SERVO_NUM_CHANNELS];
ServoConst_t ServoConst[2] = {{SERVO_MAX, SERVO_MIN, SERVO_STEPS, SERVO_PRESCALER},\
{SERVO_MAX * 4, SERVO_MIN * 4, (SERVO_STEPS + 1) * 4 - 1, SERVO_PRESCALER / 4}};
 
 
// functions
 
//! initializes software PWM system
// normaler Weise wird ein Serv-PWM Signal aller 20ms wiederholt
// Werte: rev, min, max, mid vorher über servoSet...() initialisieren und einmal servoSetPosition(...) ausführen!!!
void servoInit(void)
{ uint16_t OCValue; // set initial interrupt time
 
// disble Timer/Counter1, Output Compare A Match Interrupt
TIMSK1 &= ~(1<<OCIE1A);
// set the prescaler for timer1
if (sIdxSteps == STEPS_255) {
TCCR1B &= ~((1<<CS11) | (1<<CS10));
TCCR1B |= (1<<CS12); // prescaler 256, Servo-Schritte 185 bei 180 grd Winkel
}
else {
TCCR1B &= ~(1<<CS12);
TCCR1B |= (1<<CS11) | (1<<CS10); // prescaler 64, Servo-Schritte 740 bei 180 grd Winkel
}
// attach the software PWM service routine to timer1 output compare A
// timerAttach(TIMER1OUTCOMPAREA_INT, servoService);
// enable channels
for(uint8_t channel=0; channel < SERVO_NUM_CHANNELS; channel++) {
// set default pins assignments SERVO2 Pin 4; SERVO1 Pin 5
ServoChannels[channel].pin = (1 << (SERVO2 + channel));
}
ServoPosTics = 0; // set PosTics
// set PeriodTics
ServoPeriodTics = F_CPU / ServoConst[sIdxSteps].prescaler * SERVO_PERIODE * 1e-3;
// read in current value of output compare register OCR1A
OCValue = OCR1AL; // read low byte of OCR1A
OCValue += (OCR1AH << 8); // read high byte of OCR1A
OCValue += ServoPeriodTics; // increment OCR1A value by nextTics
// set future output compare time to this new value
OCR1AH = OCValue >> 8; // write high byte
OCR1AL = OCValue & 0x00FF; // write low byte
TIMSK1 |= (1<<OCIE1A); // enable the timer1 output compare A interrupt
}
 
uint16_t ServoSteps(void)
{
return(ServoConst[sIdxSteps].steps);
}
 
void servoSet_rev(uint8_t channel, uint8_t val)
{
ServoChannels[channel].rev = val & 0x01;
}
 
void servoSet_min(uint8_t channel, uint16_t min)
{
ServoChannels[channel].min = ServoConst[sIdxSteps].min + min;
}
 
void servoSet_max(uint8_t channel, uint16_t max)
{
ServoChannels[channel].max = ServoConst[sIdxSteps].max - max;
}
 
void servoSet_mid(uint8_t channel, uint16_t mid)
{
ServoChannels[channel].mid = mid;
ServoChannels[channel].mid_scaled = (float)(ServoChannels[channel].max - ServoChannels[channel].min)/2 + \
(mid - (float)ServoConst[sIdxSteps].steps/2) + ServoChannels[channel].min;
}
 
//! turns off software PWM system
void servoOff(void)
{
// disable the timer1 output compare A interrupt
TIMSK1 &= ~(1<<OCIE1A);
}
 
//! set servo position on channel
// input should be between 0 and ServoSteps (entspricht Maximalausschlag)
void servoSetPosition(uint8_t channel, uint16_t position)
{ uint16_t pos_scaled;
// calculate scaled position
if (ServoChannels[channel].rev != 0) position = ServoConst[sIdxSteps].steps - position;
if (position < ServoConst[sIdxSteps].steps/2)
//bei Position < Servomittelstellung Position*(Mitte - Min)/(Servoschritte/2)
pos_scaled = ((uint32_t)position*2*(float)(ServoChannels[channel].mid_scaled-ServoChannels[channel].min)/\
ServoConst[sIdxSteps].steps)+ServoChannels[channel].min;
else
//bei Position >= Servomittelstellung
pos_scaled = ServoChannels[channel].mid_scaled + (uint32_t)((position - ((float)ServoConst[sIdxSteps].steps/2)) \
* 2 * (float)(ServoChannels[channel].max-ServoChannels[channel].mid_scaled)/ServoConst[sIdxSteps].steps);
// set position
servoSetPositionRaw(channel, pos_scaled);
}
 
//! set servo position on channel (raw unscaled format)
void servoSetPositionRaw(uint8_t channel, uint16_t position)
{
// bind to limits
if (position < ServoChannels[channel].min) position = ServoChannels[channel].min;
if (position > ServoChannels[channel].max) position = ServoChannels[channel].max;
// set position
ServoChannels[channel].duty = position;
}
 
//Interruptroutine
ISR(TIMER1_COMPA_vect)
{ static uint8_t ServoChannel;
uint16_t nextTics;
uint16_t OCValue; // schedule next interrupt
 
if(ServoChannel < SERVO_NUM_CHANNELS) {
PORTD &= ~ServoChannels[ServoChannel].pin; // turn off current channel
}
ServoChannel++; // next channel
if(ServoChannel != SERVO_NUM_CHANNELS) {
// loop to channel 0 if needed
if(ServoChannel > SERVO_NUM_CHANNELS) ServoChannel = 0;
// turn on new channel
PORTD |= ServoChannels[ServoChannel].pin;
// schedule turn off time
nextTics = ServoChannels[ServoChannel].duty;
}
else {
// ***we could save time by precalculating this
// schedule end-of-period
nextTics = ServoPeriodTics-ServoPosTics;
}
// read in current value of output compare register OCR1A
OCValue = OCR1AL; // read low byte of OCR1A
OCValue += (OCR1AH <<8); // read high byte of OCR1A
OCValue += nextTics; // increment OCR1A value by nextTics
// set future output compare time to this new value
OCR1AH = OCValue >> 8; // write high byte
OCR1AL = OCValue & 0x00FF; // write low byte
 
ServoPosTics += nextTics; // set our new tic position
if(ServoPosTics >= ServoPeriodTics) ServoPosTics = 0;
}
 
/NGVideo5_8/tags/v1.11/servo.h
0,0 → 1,99
/*********************************************************************/
/* */
/* NG-Video 5,8GHz */
/* */
/* Copyright (C) 2011 - gebad */
/* */
/* This code is distributed under the GNU Public License */
/* which can be found at http://www.gnu.org/licenses/gpl.txt */
/* */
/* using */
/*! \file servo.c \brief Interrupt-driven RC Servo function library. */
/* */
/*File Name : 'servo.c' */
/*Title : Interrupt-driven RC Servo function library */
/*Author : Pascal Stang - Copyright (C) 2002 */
/*Created : 7/31/2002 */
/*Revised : 8/02/2002 */
/*Version : 1.0 */
/*Target MCU : Atmel AVR Series */
/*Editor Tabs : 4 */
/* */
/*ingroup driver_sw */
/*defgroup servo Interrupt-driven RC Servo Function Library (servo.c)*/
/*code #include "servo.h" \endcode */
/*par Overview */
/* */
/*This code is distributed under the GNU Public License */
/*which can be found at http://www.gnu.org/licenses/gpl.txt */
/* */
/*********************************************************************/
 
#ifndef SERVO_H
#define SERVO_H
 
// The numbers below good for parallax servos at an F_CPU of 20.000MHz.
// Da einige Servo's auch eien Winkel von 180 grd zulassen, Wertebereich
// entgegen den sonst üblichen. Einschränkung mit default Kalibrierung
// auf 0,9ms (45) bis 2,1ms(45) gesetzt. Je nach Servo, entspricht einen
// Winkel von etwa 180grd
// Periode default 20ms
 
#define SERVO_MAX 211 // 2,7 ms bei prescaler 256, bei prescaler 64 SERVO_MAX * 4
#define SERVO_MIN 26 // 0,33ms bei prescaler 256, bei prescaler 64 SERVO_MIN * 4
#define SERVO_STEPS 255 // Servo-Schritte von links nach rechts, Anschlagkalibrierung spielt keine Rolle
#define SERVO_PRESCALER 256 // bei prescaler 256, bei prescaler 64 SERVO_PRESCALER / 4
#define STEPS_255 0 // Servo-Schritte von links nach rechts, Anschlagkalibrierung spielt keine Rolle
#define STEPS_1023 1 // Servo-Schritte von links nach rechts, Anschlagkalibrierung spielt keine Rolle
 
typedef struct //Servo-Konstante je nach Prescaler
{
uint16_t max;
uint16_t min;
uint16_t steps;
uint16_t prescaler;
} ServoConst_t;
 
typedef struct //struct_ServoChannel
{
uint8_t pin; // hardware I/O port and pin for this channel
uint16_t duty; // PWM duty setting which corresponds to servo position
uint8_t rev; // Parameter, wie on/off; reverse; range
uint16_t min; // SERVO_MIN + Parameter min
uint16_t max; // SERVO_MAX - Parameter max
uint16_t mid_scaled; // skalierte Servomitte
int16_t mid; // Servomitte = SERVO_STEPS/2 +/- x Schritte; bei Pescaler 256 wird nur uint8_t benötigt aber bei 64
} ServoChannelType;
 
uint8_t sIdxSteps; // 0 für 255 und 1 für 1023 Schritte; Prescaler 256 oder 64
 
// functions
 
// initializes servo system
// You must run this to begin servo control
void servoInit(void);
 
// turns off servo system
// This stops controlling the servos and
// returns control of the SERVOPORT to your code
void servoOff(void);
 
// set servo position on a given channel
// servoSetPosition() commands the servo on <channel> to the position you
// desire. The position input must lie between 0 and POSITION_MAX and
// will be automatically scaled to raw positions between SERVO_MIN and
// SERVO_MAX
void servoSetPosition(uint8_t channel, uint16_t position);
 
// set raw servo position on a given channel
// Works like non-raw commands but position is not scaled. Position must
// be between SERVO_MIN and SERVO_MAX
void servoSetPositionRaw(uint8_t channel, uint16_t position);
// vor servoInit(), oder vor sei() ServoWerte mit servoSet...() initialisieren, einschließlich servoSetPosition(...)!
void servoSet_rev(uint8_t channel, uint8_t val);
void servoSet_min(uint8_t channel, uint16_t min);
void servoSet_max(uint8_t channel, uint16_t max);
void servoSet_mid(uint8_t channel, uint16_t mid);
uint16_t ServoSteps(void); // gibt "Konstante" derzeitiger Servoschritte zürück
 
#endif /* SERVO_H */
/NGVideo5_8/tags/v1.11/tracking.c
0,0 → 1,259
 
/****************************************************************/
/* */
/* NG-Video 5,8GHz */
/* */
/* Copyright (C) 2011 - gebad */
/* */
/* This code is distributed under the GNU Public License */
/* which can be found at http://www.gnu.org/licenses/gpl.txt */
/* */
/****************************************************************/
 
#include "usart.h"
#include "math.h"
#include <stdio.h>
 
#include "servo.h"
 
#define DLEFT 0
#define DRIGHT 1
#define DEG_TO_RAD 0.0174533// degrees to radians = PI / 180
#define RAD_TO_DEG 57.2957795// radians to degrees = 180 / PI
 
 
typedef struct {
double distance;
double bearing;
} geo_t;
 
geo_t geo;
int AngelPan, AngelTilt;
float Altitude;
/**************************************************************/
/* */
/* RSSI Tracking */
/* */
/**************************************************************/
 
void Tracking_RSSI(void)
{ uint16_t u0, u1;
static uint8_t direction;
static uint16_t servo1pos;
u0 = (ADC_Read(RSSI0) * (uint32_t)udbm_korr_1)/UDBM_KORR_FA;
u1 = (ADC_Read(RSSI1) * (uint32_t)udbm_korr_2)/UDBM_KORR_FA;
 
if (direction == DLEFT) {
if (u0 < u1) {
if ( servo1pos > 0) --servo1pos; // Servo Endposition?
servoSetPosition(SERVO_PAN, servo1pos); // beibehaltene Richtung ==> sofort ausführen
}
else
if (u0 > (u1 + track_hyst)) direction = DRIGHT; // Richtungwechsel, wenn Hysterese überschritten
}
else {
if (u0 > u1) {
if ( servo1pos < ServoSteps()) ++servo1pos; // Servo Endposition?
servoSetPosition(SERVO_PAN, servo1pos); // beibehaltene Richtung ==> sofort ausführen
}
else
if ((track_hyst + u0) < u1) direction = DLEFT; // Richtungwechsel, wenn Hysterese überschritten
}
}
 
/**************************************************************/
/* */
/* GPS Tracking */
/* */
/**************************************************************/
 
// Umrechnung Winkel in Servoschritte
void servo_track(uint8_t servo_nr, int16_t Angel)
{
servoSetPosition(servo_nr, (uint16_t)((uint32_t)Angel * ServoSteps() / 180));
}
 
// Anzeige eines GPS-Wertes auf LCD
void Displ_GPS_Data(uint8_t x, uint8_t y, char *description, char *data, char measure)
{
lcdGotoXY(x, y);
lcdPuts(description);
lcdPuts(data);
if (measure != '\0')
lcdPutc(measure);
}
 
// Datenempfang vom MK ==> blinkt Antennensymbol
void Displ_wiRX(void)
{ static uint8_t timer = 0;
char Sats;
if ((bat_low != 0) && (pmenu[0] == '\0')) { // nicht im Menü und nicht bei Akku leer blinken
lcdGotoXY(1, 0);
if (wi232RX) { // Datensatz vom MK empfangen?
if (timer < BLINK_PERIOD/2)
lcdPutc(5);
else {
Sats = MK.navi_data.SatsInUse; // aktuell empfangene Satellitenanzahl
if (MK.navi_data.SatsInUse > 9)
Sats = 'X'; // Anzeige einstellig, da kein Platz auf Display
else
Sats = MK.navi_data.SatsInUse + '0'; // Umrechnung Char
lcdPutc(Sats);
}
}
else
lcdPutc(':');
wi232RX = 0;
if (++timer == BLINK_PERIOD) timer = 0;
}
}
 
// Berechnung von Distanz und Winkels aus GPS-Daten home(MK eingeschaltet)
// zur aktuellen Position(nach Motorstart)
geo_t calc_geo(HomePos_t home, GPS_Pos_t pos)
{ double lat1, lon1, lat2, lon2, d1, dlat;
geo_t geo;
lon1 = home.Home_Lon;
lat1 = home.Home_Lat;
lon2 = (double)pos.Longitude / 10000000;
lat2 = (double)pos.Latitude / 10000000;
 
// Formel verwendet von http://www.kompf.de/gps/distcalc.html
// 111.3 km = Abstand zweier Breitenkreise und/oder zweier Längenkreise am Äquator
// es wird jedoch in Meter weiter gerechnet
d1 = 111300 * (double)cos((double)(lat1 + lat2) / 2 * DEG_TO_RAD) * (lon1 - lon2);
dlat = 111300 * (double)(lat1 - lat2);
// returns a value in metres http://www.kompf.de/gps/distcalc.html
geo.bearing = fmod((RAD_TO_DEG * (double)atan2(d1, dlat)) + 180, 360); // +180 besserer Vergleich mit MkCockpit
if (geo.bearing > 360) geo.bearing -= 360; // bekam schon Werte über 400
geo.distance = sqrt(d1 * d1 + dlat * dlat);
return(geo);
}
 
// MK OSD-Daten lesen und verifizieren
uint8_t OSD_Data_valid(void)
{ uint8_t ret = 0;
char *tx_osd = {"#co?]==EH\r"};
// char interval[2] = {10, '\0'};
if (rx_line_decode('O')) { // OSD-Datensatz prüfen/dekodieren
// GPS-Daten nicht zu alt und ok.
if ((rx_timeout < RX_TIME_OLD) && (MK.navi_data.NCFlags & NC_FLAG_GPS_OK)) {
ret = 1;
MK_Motor_run = MK.navi_data.FCStatusFlags & FC_FLAG_MOTOR_RUN;
}
}
// ca. 150ms keine OSD-Daten empfangen ==> sende neue Anforderung an MK
// if ((track_tx) && (rx_timeout > RX_TIMEOUT)) tx_Mk(NC_ADDRESS, 'o', interval, 1); // 10 * 10ms interval
if ((track_tx) && (rx_timeout > RX_TIMEOUT)) USART_send_Str(tx_osd); // 10 * 10ms interval
return(ret);
}
 
// MK eingeschaltet und GPS-ok, danach Motoren gestartet ==> Berechnung horizontaler/vertikaler Servowinkel
// Hauptprogramm von GPS Antennen-Nachführung
void Tracking_GPS(void)
{
if (OSD_Data_valid()) {
if (coldstart) {
// erst nach Neustart NGVideo und beim Motorstart werden Daten vom MK übernommen
if (MK.navi_data.FCStatusFlags & FC_FLAG_MOTOR_START) {
// doppelt um nur einmal nach Start zu rechnen und Anzeige ohne! Minimalistic printf version
MK_pos.Home_Lon = (double)MK.navi_data.HomePosition.Longitude / 10000000;
MK_pos.Home_Lat = (double)MK.navi_data.HomePosition.Latitude / 10000000;
MK_pos.Home_Lon_7 = MK.navi_data.HomePosition.Longitude;
MK_pos.Home_Lat_7 = MK.navi_data.HomePosition.Latitude;
MK_pos.Home_Alt = MK.navi_data.HomePosition.Altitude;
MK_pos.direction = MK.navi_data.CompassHeading;
coldstart = 0;
}
}
else {
geo = calc_geo(MK_pos, MK.navi_data.CurrentPosition);
Altitude = (float)(MK.navi_data.CurrentPosition.Altitude - MK_pos.Home_Alt) / 1000;
AngelTilt = RAD_TO_DEG * atan2(Altitude, geo.distance);
if (geo.distance < 4) { // Abstand MK- zu Antennenposition < 4m ==> Pan-Servo in Mittelstellung
geo.bearing = MK_pos.direction;
if (Altitude < 3) AngelTilt = 0; // wenn (Altitude <= 0) ist berechnet AngelTilt sowieso 0
}
// egal wo der Übergangspunkt 359, 360, 1grd ist => Winkelübergangspunkt auf 0 bzw. 180grd des Servos bringen
// 360 grd negative Winkelwerte als positive
AngelPan = fmod(geo.bearing - MK_pos.direction + 360 + 90, 360);
if (AngelPan > 360) AngelPan -= 360;
 
if (AngelTilt < 0) AngelTilt = 0;
if (AngelTilt > 180) AngelTilt = 180;
if (AngelPan >= 180) { // zwecks 360grd-Abdeckung flipt Pan-/Tilt-Servo
AngelPan = AngelPan - 180;
AngelTilt = 180 - AngelTilt;
}
 
servo_track(0, AngelPan);
servo_track(1, AngelTilt);
}
}
if ((gps_display > GPS_DISP_NONE) && (!coldstart) && (bat_low != 0)) {
if (gps_disp_clear) {
gps_disp_clear = 0;
lcdClear();
}
// makefile ohne! Minimalistic printf version
switch(gps_display) {
case GPS_DISP_CALC:
Displ_GPS_Data(0, 0, "Dir:", my_itoa(MK_pos.direction, 0, 3, 0, 0), '\xdf');
if (geo.distance < 10) // Anzeige mit einer Kommastelle
Displ_GPS_Data(8, 0, "Dis:", my_itoa((uint32_t)(geo.distance * 10), 0, 3, 1, 1), 'm');
else // Anzeige ohne Kommastelle bis 999m, Überlauf nicht abgefangen!
Displ_GPS_Data(8, 0, "Dis:", my_itoa((uint32_t)geo.distance, 0, 3, 0, 0), 'm');
Displ_GPS_Data(0, 1, "Bea:", my_itoa((uint32_t)(geo.bearing), 0, 3, 0, 0), '\xdf');
Displ_GPS_Data(8 ,1, "Alt:", my_itoa((uint32_t)(Altitude), 1, 2, 0, 0), 'm');
Displ_GPS_Data(0, 2, "Pan:", my_itoa(AngelPan, 0, 3, 0, 0), '\xdf');
Displ_GPS_Data(8, 2, "Til:", my_itoa(AngelTilt, 0, 3, 0, 0), '\xdf');
break;
case GPS_DISP_CURRENT:
Displ_GPS_Data(0, 0, "aLon:", my_itoa(MK.navi_data.CurrentPosition.Longitude, 0, 11, 7, 7), '\0');
Displ_GPS_Data(0, 1, "aLat:", my_itoa(MK.navi_data.CurrentPosition.Latitude, 0, 11, 7, 7), '\0');
Displ_GPS_Data(0, 2, "aAlt: ", my_itoa(MK.navi_data.CurrentPosition.Altitude, 1, 11, 3, 1), '\0');
break;
case GPS_DISP_HOME:
Displ_GPS_Data(0, 0, "hLon:", my_itoa(MK_pos.Home_Lon_7, 0, 11, 7, 7), '\0');
Displ_GPS_Data(0, 1, "hLat:", my_itoa(MK_pos.Home_Lat_7, 0, 11, 7, 7), '\0');
Displ_GPS_Data(0, 2, "hAlt: ", my_itoa(MK_pos.Home_Alt, 1, 11, 3, 1), '\0');
}
}
Displ_wiRX();
}
 
/************************************************************************/
/* */
/* MKCockPit Tracking */
/* */
/* http://www.pololu.com/file/download/ssc03a_guide.pdf?file_id=0J37 * */
/* */
/************************************************************************/
 
void Tracking_MKCockpit(void)
{ uint16_t ServoPos;
 
if (Get_Pololu_cmd(MK.data_decode, POLOLU_CMD)) {
switch(MK.data_decode[0]) {
// Command 0: Set Parameters(1 data byte)
case 0x00: ;
break;
// Command 1: Set Speed (1 data byte)
case 0x01: ;
break;
// Command 4: Set Position,Absollute(2 data bytes) - angepasst für default MKCockPit
case 0x04:ServoPos = MK.data_decode[2];
ServoPos = ((ServoPos << 7) | MK.data_decode[3]) / 20; // ServoPos * ServoSteps() sonst zu groß
if (ServoPos >= 60) ServoPos -= 60; else ServoPos = 0;
if (ServoPos > 180) ServoPos = 180;
servoSetPosition(MK.data_decode[1], (uint16_t)((uint32_t)ServoPos * ServoSteps() / 180));
}
}
}
/NGVideo5_8/tags/v1.11/usart.c
0,0 → 1,239
 
/****************************************************************/
/* */
/* NG-Video 5,8GHz */
/* */
/* Copyright (C) 2011 - gebad */
/* */
/* This code is distributed under the GNU Public License */
/* which can be found at http://www.gnu.org/licenses/gpl.txt */
/* */
/****************************************************************/
 
#include <avr/io.h>
#include <avr/interrupt.h>
#include "usart.h"
 
/********************************************************************************************************************/
/* */
/* MK Protokoll */
/* http://www.mikrokopter.de/ucwiki/en/SerialCommands?highlight=(command) */
/* http://www.mikrokopter.de/ucwiki/en/SerialProtocol?highlight=(protocol) */
/* */
/* Slave-Address Part */
/* 1 FC */
/* 2 NC */
/* 3 MK3MAG */
/* */
/* Auszug von Commands, nur OSD verwendet: */
/* Received by NC | Sent by NC */
/* | since NC */
/* Description ID Address Data | ID Address Data Firmware */
/* Debug Request 'd' AnyAddr u8 AutoSendInterval. Value is | 'D' SlaveAddr Debug Data Struct */
/* multiplied by 10 in receiver and , | */
/* then used as milliseconds. Subsciption | */
/* needs to be renewed every 4s. | */
/* Request OSD 'o' NC-Addr 1 byte sending interval (in 10ms steps)| 'O' NC-Addr NaviDataStruct 0.12h */
/* -Data | */
/* Redirect UART 'u' NC-Addr 1 byte param for uart selector (0=FC, | - - - 0.12h */
/* 1=MK3MAG, 2=MKGPS), can be switched | */
/* back to NC debug by sending the magic | */
/* packet "0x1B,0x1B,0x55,0xAA,0x00" | */
/* Set 3D-Data 'c' AnyAddr u8 Interval | 'C' NC-Addr struct Data3D 0.14a */
/* Interval */
/* */
/********************************************************************************************************************/
 
char rx_buffer[RXD_BUFFER_SIZE];
 
volatile uint8_t rx_len;
volatile uint8_t rx_ready = 0;
uint8_t rx_GPS;
char start;
 
/**************************************************************/
/* */
/* USART */
/* 8 Datenbits, 1 Stopbit, keine Parität */
/* */
/**************************************************************/
 
void USART_Init(unsigned int baud)
{ uint16_t ubrx;
 
ubrx = F_CPU/(baud * 16L) - 1;
/* Set baud rate */
UBRR0H = (unsigned char)(ubrx>>8);
UBRR0L = (unsigned char)ubrx;
/* RX Complete Interrupt Enable, Enable receiver and transmitter */
UCSR0B = (1<<RXCIE0) | (1<<RXEN0) | (1<<TXEN0);
/* Asynchronous USART, no Parity, Set frame format: 8data, 1stop bit */
UCSR0C = (1<<UCSZ01) | (1<<UCSZ00); // 8data Bit
}
 
void USART_send_Chr(unsigned char data)
{
/* Wait for empty transmit Puffer */
while ( !( UCSR0A & (1<<UDRE0)) ) ;
/* Put data into Puffer, sends the data */
UDR0 = data;
}
 
void USART_send_Str(char *str )
{
while (*str) {
USART_send_Chr(*str);
str++;
}
}
 
/*
// verwendet Orginal H&I MK-Software http://www.mikrokopter.de/ucwiki/en/SerialProtocol?highlight=(protocol)
// kann auch vereinfacht werden ==> gleich kodierten String senden char *tx_osd = {"#co?]==EH\r\0"}
// Funktion getestet und funktioniert
void tx_Mk(unsigned char addr, char cmd, char *data, uint8_t len)
{ char tx_buffer[TXD_BUFFER_SIZE];
uint8_t tx_i = 0;
uint8_t i = 0;
unsigned char a,b,c;
unsigned int tmpCRC = 0;
 
tx_buffer[tx_i++] = '#'; // Start-Byte
tx_buffer[tx_i++] = 'a' + addr; // Adress
tx_buffer[tx_i++] = cmd; // Command
// code64
while (len) {
if (len) { a = data[i++]; len--;} else a = 0;
if (len) { b = data[i++]; len--;} else b = 0;
if (len) { c = data[i++]; len--;} else c = 0;
tx_buffer[tx_i++] = '=' + (a >> 2);
tx_buffer[tx_i++] = '=' + (((a & 0x03) << 4) | ((b & 0xf0) >> 4));
tx_buffer[tx_i++] = '=' + (((b & 0x0f) << 2) | ((c & 0xc0) >> 6));
tx_buffer[tx_i++] = '=' + (c & 0x3f);
}
// add crc
for (i = 0; i < tx_i; i++) {
tmpCRC += tx_buffer[i];
}
tmpCRC %= 4096;
tx_buffer[i++] = '=' + tmpCRC / 64;
tx_buffer[i++] = '=' + tmpCRC % 64;
tx_buffer[i++] = '\r'; // End-Byte
 
tx_buffer[i++] = '\0'; // USART_send_Str(...) ==> End-while
USART_send_Str(tx_buffer);
} */
 
ISR(USART0_RX_vect)
{ char received;
static uint8_t line_flag = 1;
static char* ptr_write = rx_buffer;
static uint8_t frame = 6;
// von '#' bis '\r' Puffer, einschließlich Satzzeichen schreiben
received = UDR0;
if (rx_ready == 0) {
if ((received == start) && line_flag) { // start '#' oder 0x80
line_flag = 0; // MK-Datensatzanfang wurde erkannt
ptr_write = rx_buffer; // Schreibzeiger auf Anfang Puffer setzen
rx_len = 0;
}
if (line_flag == 0) { // MK/Pololu-Datensatz ?
*ptr_write = received;
rx_len++;
 
/* GPS Datensatzende */
if (rx_GPS) {
if (received == '\r') { // Ende MK-Datensatz ?
line_flag = 1;
rx_ready = 1; // Puffer Schreiben sperren, MK-Datensatz kann nun verarbeitet werden
}
}
/* Pololu Micro Serial stark reduziert/vereinfacht; rx_len-Abfrage 1 höher ==> bereits incrementiert */
else {
if ((rx_len == 2) && (received != 0x01)) line_flag = 1; // device
if ((rx_len == 3) && (received > 0x01)) frame = 6; else frame = 5; // command
if (rx_len == frame) {
line_flag = 1;
rx_ready = 1; // Puffer Schreiben sperren, Pololu-Datensatz kann nun verarbeitet werden
}
}
 
ptr_write++;
if(rx_len == RXD_BUFFER_SIZE) line_flag = 1; // ungültiger MK/Pololu-Datensatz ? ==> neu beginnen
}
}
}
 
// verwendet aus Orginal H&I MK-Software http://www.mikrokopter.de/ucwiki/en/SerialProtocol?highlight=(protocol)
void Decode64(char *ptrOut, uint8_t len, uint8_t ptrIn)
{ unsigned char a,b,c,d;
unsigned char ptr = 0;
unsigned char x,y,z;
while(len)
{
a = rx_buffer[ptrIn++] - '=';
b = rx_buffer[ptrIn++] - '=';
c = rx_buffer[ptrIn++] - '=';
d = rx_buffer[ptrIn++] - '=';
 
x = (a << 2) | (b >> 4);
y = ((b & 0x0f) << 4) | (c >> 2);
z = ((c & 0x03) << 6) | d;
if(len--) ptrOut[ptr++] = x; else break;
if(len--) ptrOut[ptr++] = y; else break;
if(len--) ptrOut[ptr++] = z; else break;
}
}
 
// eingearbeitet Orginal H&I MK-Software mkprotocol.h und mkprotocol.c
uint8_t rx_line_decode(char rx_ID)
{ uint8_t ret = 0;
uint8_t crc1,crc2;
int tmpCRC = 0;
// rx_ready gleichzeitig usart rx_buffer schreiben gesperrt
if ((rx_ready == 1) && (rx_len > 0) && (rx_buffer[2] == rx_ID)) {
// Checksumme
// verwendet http://www.mikrokopter.de/ucwiki/en/SerialProtocol?highlight=(protocol)
for(uint8_t i = 0; i < rx_len - 3;i++) {
tmpCRC += rx_buffer[i];
}
tmpCRC %= 4096;
crc1 = '=' + tmpCRC / 64;
crc2 = '=' + tmpCRC % 64;
if ((crc1 == rx_buffer[rx_len-3]) && (crc2 == rx_buffer[rx_len-2])) {
Decode64(MK.data_decode, rx_len - 6, 3); // Daten ohne Satzzeichen, header und crc
ret = 1;
}
cli();
rx_timeout = 0; // wenn kein gültiger Datensatz für rx_ID ==> Counter wird nicht mehr rückgesetzt
sei();
}
// für Blinken des Antennenzeichens, MK antwortet immer mit cmd Großbuchstaben
if ((rx_timeout < RX_TIME_OLD) && (rx_buffer[2] >= 'A') && (rx_buffer[2] <= 'Z')) wi232RX = 1;
rx_ready = 0; // Puffer Schreiben entsperren, neuer MK-Datensatz kann wieder empfangen/gepuffert werden
return(ret);
}
 
void USART_RX_Mode(uint8_t tracking)
{
rx_GPS = (tracking == TRACKING_GPS);
if (rx_GPS) start ='#'; else start = 0x80;
}
 
uint8_t Get_Pololu_cmd(char *ptrOut, uint8_t ptrIn)
{
rx_len -=2; // ohne Start-Char und device
if (rx_ready == 1) {
for (uint8_t i = 0; i < rx_len; i++)
ptrOut[i] = rx_buffer[ptrIn++]; // ab Pololu-Command
}
else
rx_len = 0;
rx_ready = 0; // Puffer Schreiben entsperren, neuer Pololu-Datensatz kann wieder empfangen/gepuffert werden
return(rx_len);
}
/NGVideo5_8/tags/v1.11/usart.h
0,0 → 1,120
 
/****************************************************************/
/* */
/* NG-Video 5,8GHz */
/* */
/* Copyright (C) 2011 - gebad */
/* */
/* This code is distributed under the GNU Public License */
/* which can be found at http://www.gnu.org/licenses/gpl.txt */
/* */
/****************************************************************/
 
#ifndef USART_H_
#define USART_H_
 
#define TRACKING_RSSI 1
#define TRACKING_GPS 2
#define TRACKING_MKCOCKPIT 3
 
#define RXD_BUFFER_SIZE 150 //Puffergröße in Byte
#define TXD_BUFFER_SIZE 20
#define ANY_ADDRESS 0
#define FC_ADDRESS 1
#define NC_ADDRESS 2
 
#define FC_FLAG_MOTOR_RUN 0x01
#define FC_FLAG_FLY 0x02
#define FC_FLAG_CALIBRATE 0x04
#define FC_FLAG_MOTOR_START 0x08
 
#define NC_FLAG_GPS_OK 0x80
 
#define RX_TIMEOUT 420 // 210ms
#define RX_TIME_OLD 3 * RX_TIMEOUT // Grenze, Datensatz viel zu alt
 
//volatile unsigned char buffercounter;
 
//char data_decode[RXD_BUFFER_SIZE];
volatile uint16_t rx_timeout;
 
void USART_Init(unsigned int baud);
void USART_send_Str(char *str );
uint8_t rx_line_decode(char rx_ID);
//void tx_Mk(unsigned char addr, char cmd, char *data, uint8_t len);
 
// Orginal H&I MK-Software
typedef struct
{
int32_t Longitude; // in 1E-7 deg
int32_t Latitude; // in 1E-7 deg
int32_t Altitude; // in mm
uint8_t Status; // validity of data
} __attribute__((packed)) GPS_Pos_t;
 
typedef struct
{
uint16_t Distance; // distance to target in dm
int16_t Bearing; // course to target in deg
} __attribute__((packed)) GPS_PosDev_t;
 
typedef struct
{
uint8_t Version; // version of the data structure
GPS_Pos_t CurrentPosition; // see ubx.h for details
GPS_Pos_t TargetPosition;
GPS_PosDev_t TargetPositionDeviation;
GPS_Pos_t HomePosition;
GPS_PosDev_t HomePositionDeviation;
uint8_t WaypointIndex; // index of current waypoints running from 0 to WaypointNumber-1
uint8_t WaypointNumber; // number of stored waypoints
uint8_t SatsInUse; // number of satellites used for position solution
int16_t Altimeter; // hight according to air pressure
int16_t Variometer; // climb(+) and sink(-) rate
uint16_t FlyingTime; // in seconds
uint8_t UBat; // Battery Voltage in 0.1 Volts
uint16_t GroundSpeed; // speed over ground in cm/s (2D)
int16_t Heading; // current flight direction in ° as angle to north
int16_t CompassHeading; // current compass value in °
int8_t AngleNick; // current Nick angle in 1°
int8_t AngleRoll; // current Roll angle in 1°
uint8_t RC_Quality; // RC_Quality
uint8_t FCStatusFlags; // Flags from FC
uint8_t NCFlags; // Flags from NC
uint8_t Errorcode; // 0 --> okay
uint8_t OperatingRadius; // current operation radius around the Home Position in m
int16_t TopSpeed; // velocity in vertical direction in cm/s
uint8_t TargetHoldTime; // time in s to stay at the given target, counts down to 0 if target has been reached
uint8_t RC_RSSI; // Receiver signal strength (since version 2 added)
int16_t SetpointAltitude; // setpoint for altitude
uint8_t Gas; // for future use
uint16_t Current; // actual current in 0.1A steps
uint16_t UsedCapacity; // used capacity in mAh
} __attribute__((packed)) NaviData_t;
 
typedef union
{
char data_decode[RXD_BUFFER_SIZE];
NaviData_t navi_data;
} MK_t;
 
MK_t MK;
 
typedef struct
{
double Home_Lon;
double Home_Lat;
int32_t Home_Lon_7; // in 1E-7 deg
int32_t Home_Lat_7; // in 1E-7 deg
int32_t Home_Alt; // in mm
int16_t direction; // ermittelte Konstante aus Mittelposition Antenne geo.bearing - navi_data.CompassHeading
} __attribute__((packed)) HomePos_t;
 
HomePos_t MK_pos;// steht hier nur wegen Vermeidung Compiler-Warnung
uint8_t wi232RX; // Statusflag für Empfangszeichen auf lcd
 
void USART_RX_Mode(uint8_t tracking);
uint8_t Get_Pololu_cmd(char *ptrOut, uint8_t ptrIn);
 
#endif /* USART_H_ */
 
/NGVideo5_8/tags/v1.11
Property changes:
Added: bugtraq:number
+true
\ No newline at end of property