Subversion Repositories Projects

Compare Revisions

Ignore whitespace Rev 1068 → Rev 1069

/NGVideo5_8/tags/v1.10/Hexfiles/NGVideo_MEGA644.hex
0,0 → 1,1631
:100000000C9467050C94BB070C94F2070C948405C0
:100010000C9484050C9484050C9484050C9484053C
:100020000C9484050C9484050C9484050C944F075F
:100030000C9484050C941B290C9484050C94840561
:100040000C9484050C9484050C946F250C94840501
:100050000C94C9290C9484050C9484050C94840593
: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
:100A100000303A3200303A3300303A3400A1095401
:100A200022A3097220A6090E20A9093422AC094488
:100A300023B009F922B409C41FB7091422BA0972F4
:100A40001FBE09EF21C2096C1FC709E61ECC09446D
:100A50001ED109A41DD609C921DA09661FDF09E0E4
:100A60001EE4093E1EE9099E1DEE09A921F109C7F0
:100A70001CF5096F1CF9098921FC090C1C000AC529
:100A80001B040A491B070A381B0A0A66210D0ACEF5
:100A900022110ACE22150ACE22190A9E22202010E7
:100AA0001010102020202018181818202020201C9A
:100AB0001C1C1C202020201E1E1E1E202020201F4B
:100AC0001F1F1F20200608141314080620001124DD
:100AD0001FBECFEFD0E1DEBFCDBF12E0A0E0B1E09E
:100AE000E2E8F4E602C005900D92A633B107D9F70B
:100AF00014E0A6E3B2E001C01D92AE33B107E1F706
:100B00000E948F230C943F320C9400008150282FB8
: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
:100CB000C801B7010E94F230C901DF91CF911F91A5
:100CC0000F91FF90EF90DF90CF90BF90AF909F90EB
:100CD0000895AF92BF92CF92DF92EF92FF920F935F
:100CE0001F931C9A1C9890E0A0E0B0E0BC01CD01DD
:100CF0000E947C2E5B016C0120E030E44CE955E45D
:100D00000E94F32F7B018C0120E030E040E85FE39C
:100D10000E94DC2D88231CF461E070E024C0C8012F
:100D2000B70120E03FEF4FE757E40E94E82F181685
:100D3000B4F4C601B50120E030E040E251E40E9485
:100D4000F32F0E94502E84EF91E005C0FC013197F3
:100D5000F1F76150704061157105C1F707C0C80116
:100D6000B7010E94502ECB010197F1F71C9A1C98F5
:100D70001F910F91FF90EF90DF90CF90BF90AF90B9
:100D800008959F92AF92BF92CF92DF92EF92FF921F
:100D90000F931F93982EE62E0E946906FF2400E011
:100DA00010E0C801B7010E947C2E5B016C0120E0BD
:100DB00030E44CE955E40E94F32F7B018C0120E0E4
:100DC00030E040E85FE30E94DC2D88231CF461E002
:100DD00070E024C0C801B70120E03FEF4FE757E4BF
:100DE0000E94E82F1816B4F4C601B50120E030E0E7
:100DF00040E251E40E94F32F0E94502E84EF91E0D4
:100E000005C0FC013197F1F7615070406115710523
:100E1000C1F707C0C801B7010E94502ECB0101974E
:100E2000F1F7892D0E9469061F910F91FF90EF90B5
:100E3000DF90CF90BF90AF909F900895CF93DF93B6
:100E4000EC0180918E0190918F010F97209190017C
:100E500030919101821B930B6BE070E00E94DE30B9
:100E6000A62FB0E040E050E020E030E0FE01E20FCD
:100E7000F31F80918E0190918F01841B950B9183BC
:100E800080834A0F5B1F2E5F3F4F2831310571F77A
:100E9000862F65E00E94D230DF91CF9108951F9296
:100EA0000F920FB60F9211242F938F939F93AF93AE
:100EB000BF9384E68093B2008091EC028F3F29F0CB
:100EC0008091EC028F5F8093EC028091AB028F3FA8
:100ED00029F08091AB028F5F8093AB028091D302A7
:100EE0009091D4028C5E944048F48091D30290910A
:100EF000D40201969093D4028093D3028091380259
:100F0000823079F580913B02882359F18091C402A7
:100F10008823A1F08091400290914102A091420269
:100F2000B09143020196A11DB11D809340029093A0
:100F30004102A0934202B093430213C080913C024D
:100F400090913D02A0913E02B0913F020196A11DF9
:100F5000B11D80933C0290933D02A0933E02B0935A
:100F60003F02BF91AF919F918F912F910F900FBE34
:100F70000F901F9018951F920F920FB60F92112489
:100F80008F939F938091EC028F3438F08091EC0224
:100F9000823518F41092B0020AC091E09093B0022A
:100FA0008091EE02882319F4149A9093C4029091D0
:100FB000B0028091EE02981761F48091CA028823F2
:100FC00021F414981092C40204C0149A81E0809312
:100FD000C4021092EC029F918F910F900FBE0F9060
:100FE0001F9018951F920F920FB60F9211248F9396
:100FF0009F938091AB028F3438F08091AB028235A1
:1010000018F41092EE020AC081E08093EE02809103
:10101000B002882319F414981092C4029091B0027F
:101020008091EE02981761F48091CA02882321F41E
:1010300014981092C40204C0149A81E08093C402F0
:101040001092AB029F918F910F900FBE0F901F9047
:1010500018950E94BE0580918703882331F0F8948B
:101060001092870378940E94D90508954F925F9259
:101070006F927F928F929F92AF92BF92CF92DF92A8
:10108000EF92FF920F931F93CF93DF93EC013A01FE
:101090004B01122FCB01BA012CE330E040E050E0CD
:1010A0000E94F2305B016C01412E552447FC5094A4
:1010B000C40DD51DEE24FF24012F10E00150104077
:1010C00018C0B501C6012AE030E040E050E00E94BF
:1010D000F230605D6883B501C6012AE030E040E08F
:1010E00050E00E94F23059016A010894E11CF11CA1
:1010F0002197C2018E199F098017910714F7C40127
:10110000B3012CE330E040E050E00E94F230CA012D
:10111000B901DF91CF911F910F91FF90EF90DF9078
:10112000CF90BF90AF909F908F907F906F905F9087
:101130004F9008951F9310913802109238020E9428
:10114000792680E060E00E94DA24812F1F910895C3
:101150000F931F93DF93CF93CDB7DEB729970FB6C9
:10116000F894DEBF0FBECDBF20EA3FE040E050E084
:101170000E94F230BA0119868E010F5F1F4FC8011D
:10118000A90127E00E943608AB01BC01C80124E098
:101190000E943608AB01BC01C80121E00E9436085C
:1011A0008AE38B838E83C8010E94E82429960FB6B8
:1011B000F894DEBF0FBECDBFCF91DF911F910F918D
:1011C000089586E061E00E94DA2460913C0270910B
:1011D0003D0280913E0290913F020E94A80886E065
:1011E00062E00E94DA246091400270914102809195
:1011F0004202909143020E94A80808958091F00253
:10120000813021F41092F00280E104C081E08093EB
:10121000F0028CE08093BE0286E090E06091F002E4
:101220000E94143287E090E06091BE020E94143266
:10123000089580913802833061F4E091A501F0E0D7
:10124000EE0FFF1FEE0FFF1FEA59FE4F80819181C5
:1012500004C080917E0190917F010E94972908959A
:101260000E94DD26BC017695679580E00E94C62726
:1012700081E060E070E00E94C6270895DF92EF925F
:10128000FF920F931F93D82E7B010E94DD2600272B
:10129000F7FC0095102F9C0140E050E0C801B70119
:1012A0000E94B33024EB30E040E050E00E94F23086
:1012B0008D2DB9010E94C6271F910F91FF90EF90CD
:1012C000DF9008950F931F93CF93DF9385E00E94E3
:1012D0001806A0E0B0E0209192013091930140E027
:1012E00050E0BC01CD010E94B33047E09695879550
:1012F000779567954A95D1F7EB0186E00E9418062D
:10130000A0E0B0E0209194013091950140E050E0E0
:10131000BC01CD010E94B33037E096958795779553
:1013200067953A95D1F7809189028823B1F4C61761
:10133000D70740F48091870290918802009711F1BD
:1013400001971CC08091A401680F711D6C177D0767
:1013500050F581E08093890226C06C177D07D0F498
:1013600000918702109188020E94DD260817190754
:1013700048F48091870290918802019690938802A8
:1013800080938702609187027091880280E00E94BA
:10139000C62709C08091A401C80FD11DC617D70761
:1013A00010F410928902DF91CF911F910F9108954F
:1013B000EF92FF920F931F93CF93DF93E82EC6E92E
:1013C000D1E00AE110E0FF2429813A814B815C8160
:1013D0008D819E81EE2089F4369527953695279547
:1013E0003A83298356954795569547955C834B8359
:1013F000969587959695879511C0220F331F220FDA
:10140000331F3A832983440F551F440F551F5C83B4
:101410004B83880F991F880F991F03969E838D8396
:1014200069817A818F2D0E94F9266B817C818F2DB5
:101430000E9416276D817E818F2D0E943527CE0157
:10144000B80147E050E00E940A32F39427960F5CFF
:101450001F4F82E0F81609F0B7CF0E943009DF91E4
:10146000CF911F910F91FF90EF9008950F931F93CD
:10147000182F062F823078F462E0681B8FE00E94FC
:10148000DA2480E20E9469241F5F8FE0612F0E94AE
:10149000DA24802F0CC08FE061E00E94DA2480E221
:1014A0000E9469248FE062E00E94DA2480E20E94B8
:1014B00069241F910F910895EF92FF920F931F934C
:1014C000DF93CF93CDB7DEB72E970FB6F894DEBF7C
:1014D0000FBECDBF7B018C01DE011196E2E1F2E08F
:1014E0008EE001900D928150E1F78E2D805D0E947B
:1014F000692480E091E00E94E8240894E108F10862
:1015000001091109F701EE0FFF1FEC0FFD1F81818B
:1015100092810E94E82483E091E00E94E8242E96C4
:101520000FB6F894DEBF0FBECDBFCF91DF911F91F4
:101530000F91FF90EF900895EF92FF920F931F93FA
:10154000F82EE92E062F80E00E94DA2410E080E2D7
:101550000E9469241F5F1031D1F7EF2DFE2DDF01AE
:101560000D900020E9F7EA1BFB0B7196F695E795C5
:101570008E2F602F0E94DA248F2D9E2D0E94E8244A
:101580001F910F91FF90EF900895AF92BF92CF926D
:10159000DF92EF92FF920F931F93DF93CF93CDB71C
:1015A000DEB72C970FB6F894DEBF0FBECDBF6C012F
:1015B0008E010F5F1F4F5C0178012BE0A4E07FEFED
:1015C000A03241F0F501808191818417950710F4D4
:1015D000272FA0E2F701A1937F017F5F82E090E0D7
:1015E000A80EB91E7B3061F72F3FC1F0332727FDCE
:1015F0003095F901EE0FFF1FEC0DFD1D80819181EB
:10160000841B950B70E00E94DE30FE013196E20FE4
:10161000F31F6083653010F084E080838DE0E82E56
:10162000F12CEC0EFD1EF80181918F010E946924BE
:101630000E151F05C1F72C960FB6F894DEBF0FBE2E
:10164000CDBFCF91DF911F910F91FF90EF90DF9071
:10165000CF90BF90AF900895CF92DF92EF92FF921C
:101660000F931F93CF93DF93082F6B01142F85E007
:101670000E941806A0E0B0E0209192013091930101
:1016800040E050E0BC01CD010E94B33037E09695B8
:101690008795779567953A95D1F77B0186E00E940B
:1016A0001806A0E0B0E0209194013091950140E04F
:1016B00050E0BC01CD010E94B33027E0969587959C
:1016C000779567952A95D1F7EB01023001F5E6167B
:1016D000F70670F4109275028091EC028F3FC9F406
:1016E0008091AB028F3FA9F414981092C40211C0EC
:1016F00091E0909375028091EC028F3F51F48091BC
:10170000AB028F3F31F4149A9093C40202C000934D
:101710007502112309F447C0023011F01BEF1EC0FF
:101720009091B0028091EE02981799F09091EC029E
:101730008091AB0289238F3F61F08091B0028823B2
:1017400019F41092760203C081E08093760213E7C9
:1017500005C0809175028093760214E6F6018081BF
:1017600091818E159F0520F48C179D0708F410E2D7
:1017700082E061E00E94DA24C6016091C202A70102
:101780000E94C50A82E062E00E94DA24C6016091EC
:10179000C202AE010E94C50A023029F4809176028D
:1017A000612F0E94360A80917502DF91CF911F91BF
:1017B0000F91FF90EF90DF90CF9008958091BF023E
:1017C000882381F0F8941092BF0278946091A6016A
:1017D0007091A701809137024091A8010E942C0BC3
:1017E0008093CA0208958091A801882341F18091D5
:1017F000A901882321F581E060E00E94DA2480912C
:10180000B502882371F080918602863010F485E05D
:1018100009C0809123038A3010F088E503C0805D01
:1018200001C08AE30E9469241092B5028091860269
:101830008F5F809386028C3011F410928602089597
:10184000CF92DF92EF92FF920F937A0169010E948B
:10185000DA24C7010E94E824C6010E94E82400237C
:1018600019F0802F0E9469240F91FF90EF90DF9074
:10187000CF9008950F931F93DF93CF93CDB7DEB72B
:1018800027970FB6F894DEBF0FBECDBFDC01CB01AA
:10189000880F991F880F991F8A599E4FFC016081FC
:1018A0007181828193818E010F5F1F4FA8012AE011
:1018B00030E00E94B231C80161E00E949C0A279684
:1018C0000FB6F894DEBF0FBECDBFCF91DF911F9151
:1018D0000F9108954F925F926F927F928F929F9295
:1018E000AF92BF92CF92DF92EF92FF920F931F932E
:1018F000DF93CF9300D000D0CDB7DEB72B013C01F2
:1019000029833A834B835C83DF88B88C80E40E9410
:101910002326882329F480E40E942E268823E1F0E0
:101920004E145F046006710648F40894411C511C73
:10193000611C711C8B2D0E945F2606C0DD2021F0EA
:1019400049805A806B807C808C2D6A2D0E94DA241D
:10195000C301B201F401099580E80E94232688237F
:1019600029F480E80E942E268823F1F089819A814B
:10197000AB81BC8184159505A605B70548F408948C
:1019800041085108610871088B2D0E945F2604C030
:10199000DD2011F0270138018C2D6A2D0E94DA24F8
:1019A000C301B201F4010995B201C3010F900F9078
:1019B0000F900F90CF91DF911F910F91FF90EF90BB
:1019C000DF90CF90BF90AF909F908F907F906F905F
:1019D0005F904F9008950F931F93CF93DF938C01E7
:1019E000FC018081882309F1C0E0D0E0FE01EE0F08
:1019F000FF1FEE0FFF1FE35EF54F65917491C80165
:101A00000E946631892B69F4CE01880F991F880FD7
:101A1000991F815E954FFC0125913491F90109953B
:101A200004C02196C032D10509F7DF91CF911F91F3
:101A30000F9108951F93182F8091AD02882319F0FC
:101A400060E070E005C00E94DD26BC0176956795D8
:101A50008091AD020E94C62710933802112389F4A9
:101A600020E044EF51E008C0FA013197F1F7019707
:101A7000D9F72F5F223019F080ED97E0F5CF0E9463
:101A8000C02789EA91E00E94EB0C1F9108958533ED
:101A9000910540F0FC01EE0FFF1FEF5EF64F6591E0
:101AA00074911CC020918D01213029F0880F991F5D
:101AB000223079F408C0FC01EE0FFF1FE955F74F03
:101AC000659174910BC0FC01EF5EF64F65917491C6
:101AD00005C0FC01E35CF74F6591749184E492E0EA
:101AE0000E946F3184E492E00895DF93CF9300D099
:101AF0000F92CDB7DEB7DE011196EBEDF1E023E0FA
:101B000001900D922150E1F7FE01E60FF71F818150
:101B100090E00E94470D61E00E949C0A0F900F9098
:101B20000F90CF91DF910895DF93CF9300D0CDB781
:101B3000DEB72DE329832EE32A83FE01E60FF71F8C
:101B4000818190E00E94470D61E00E949C0A0F9005
:101B50000F90CF91DF910895611571058105910571
:101B600019F485E290E002C086E290E00E94470D01
:101B70000E94E8240895DF92EF92FF920F931F9343
:101B8000DF93CF9300D000D00F92CDB7DEB77B01AB
:101B90008C018EE090E00E94470DFC010190002036
:101BA000E9F73197DE2ED81AE114F1040105110589
:101BB00039F08FE1E816F1040105110529F510C08F
:101BC0008FE090E00E94470DFC0101900020E9F7B2
:101BD0003197E81BF90B1D2D1E0F8FE090E00FC011
:101BE00080E190E00E94470DFC0101900020E9F7A0
:101BF0003197E81BF90B1D2D1E0F80E190E00E942C
:101C0000470D0E94E82437C0C801B7012AE030E040
:101C100040E050E00E94B330DC01CB017E0108942B
:101C2000E11CF11CB7014AE050E00E94913180E2D2
:101C30000E946924C7010E94E82481E190E00E948B
:101C4000470D0E94E824F70101900020E9F78F0179
:101C5000015010400E191F0981E190E00E94470DCC
:101C6000DC010D900020E9F71197A81BB90B1D2D81
:101C7000100F1F5F1A0F00E1011B10E004C080E28B
:101C80000E9469241F5F1017D0F30F900F900F90E0
:101C90000F900F90CF91DF911F910F91FF90EF90D8
:101CA000DF900895DF93CF9300D0CDB7DEB725E264
:101CB00029832BE22A83FE01E60FF71F818190E042
:101CC0000E94470D61E00E949C0A0F900F90CF91F7
:101CD000DF910895DF93CF9300D000D0CDB7DEB76A
:101CE00025E2298321E42A8328E22B8322E42C8322
:101CF000FE01E60FF71F818190E00E94470D61E031
:101D00000E949C0A0F900F900F900F90CF91DF913F
:101D10000895DF93CF9300D00F92CDB7DEB7DE01E9
:101D20001196ECEEF1E023E001900D922150E1F7E5
:101D3000FE01E60FF71F818190E00E94470D61E0F0
:101D40000E949C0A0F900F900F90CF91DF91089501
:101D500080E060E00E94DA2486E490E00E94470D73
:101D60000E94E8248091F002882319F484E390E033
:101D700002C085E490E00E94470D0E94E82487E4B9
:101D800090E00E94470D0E94E82420E044EF51E0DB
:101D900008C0FA013197F1F70197D9F72F5F2F317A
:101DA00019F088EE93E0F5CF0E94B92408950F93BF
:101DB0001F93082F90E00E94470DFC010190002026
:101DC000E9F73197E81BE031D8F480E190E08E1B11
:101DD000910995958795182F823098F0825060E090
:101DE0000E94DA2487E091E00E94E824802F90E0AE
:101DF0000E94470D0E94E82480E20E94692416C0D8
:101E000010E080E060E00E94DA248AE20E94692407
:101E1000812F60E00E94DA24802F90E00E94470D1D
:101E20000E94E8248FE060E00E94DA248AE20E94A7
:101E300069241F910F910895CF92DF92EF92FF9244
:101E40000F931F93CF93DF93EC01D42E662311F4ED
:101E5000F42E02C0F62EFA94EE243EE0C32E82E069
:101E60006E2D0E94DA248E010F0D111DF801808164
:101E700090E00E94470D0E94E824F801808190E0E4
:101E80000E94470DFC0101900020E9F73197E81B03
:101E9000F90B0C2D0E1B04C080E20E946924015036
:101EA0001016D4F3FD1410F0FF2401C0F394E39452
:101EB000F3E0EF16A1F6DF91CF911F910F91FF9004
:101EC000EF90DF90CF9008951F93182F0E94B924B0
:101ED00088E190E00E94470D60E00E949C0A89E141
:101EE00090E00E94470D61E00E949C0A812F90E0E3
:101EF0000E94470D62E00E949C0A20E044EF51E0FE
:101F000008C0FA013197F1F70197D9F72F5F2F3108
:101F100019F088EE93E0F5CF1F9108950E94B9243F
:101F200086E190E00E94470D60E00E949C0A87E1F4
:101F300090E00E94470D61E00E949C0A08952F9254
:101F40003F924F925F926F927F928F929F92AF9249
:101F5000BF92CF92DF92EF92FF920F931F93DF9386
:101F6000CF93CDB7DEB72B970FB6F894DEBF0FBE79
:101F7000CDBF5B016C014B83122F402E5E2C83E39F
:101F800090E00E94470DFC0120812983D7FC02C00C
:101F90001A820AC0D094C094B094A094A11CB11C21
:101FA000C11CD11C31E03A835B81552321F080E3D1
:101FB0008093790201C01150612E7724F301E75814
:101FC000FD4F118251105394812F992787FD9095D1
:101FD00049E7842E42E0942E880E991EEE24FF24B9
:101FE0009D838C839B81892F90E09F838E838301C7
:101FF000041911091801250C311CD801A758BD4F2F
:10200000B987A88736C0EA85FB850E171F0739F404
:10201000442029F0E981A885B985EC9319C0C6014F
:10202000B5012AE030E040E050E00E941431605DEC
:10203000D4016C93C601B5012AE030E040E050E0E5
:102040000E941431C901DA015C016D01442059F08C
:10205000451448F0EA85FB852E163F0621F4F10170
:10206000E758FD4F10820894E11CF11C0894810888
:1020700091082C813D812E193F093B872A878E814B
:102080009F81281739070CF0BECFE9E7F2E020E086
:1020900030E04DE290E213C0AB81AA2351F0BA8147
:1020A000BB2339F0803321F482815981851709F4EB
:1020B00040832F5F3F4F8081803341F49193818132
:1020C000A9818A1719F02615370534F389E792E0BC
:1020D0002B960FB6F894DEBF0FBECDBFCF91DF9128
:1020E0001F910F91FF90EF90DF90CF90BF90AF9036
:1020F0009F908F907F906F905F904F903F902F9028
:102100000895AF92BF92CF92DF92EF92FF920F931A
:102110001F935B016C017B010E94DD2696958795DC
:10212000E81AF90A0027F7FC0095102FC801B7013B
:1021300041E023E000E0EE240E949F0F0E94E8248B
:102140008091AD02B5010E9435271091AD020E9429
:10215000DD26BC0176956795812F0E94C6271F91C9
:102160000F91FF90EF90DF90CF90BF90AF900895C8
:10217000EF920F9340E023E000E0EE240E949F0FD7
:102180000E94E8240F91EF900895EF92FF920F9331
:102190001F93CF93DF937B018C010E94DD26EC011E
:1021A000C801B7010E94B8108091AD02B7010E942A
:1021B00016272091AD02822F90E0FC0173E0EE0F14
:1021C000FF1F7A95E1F7E81BF90BEA56FE4F808175
:1021D000882311F0C0E0D0E0822FBE010E94C62704
:1021E000DF91CF911F910F91FF90EF900895EF92A3
:1021F000FF920F931F937B018C010E94B810809176
:10220000AD02B7010E94F9268091AD0290E0FC0179
:10221000A3E0EE0FFF1FAA95E1F7E81BF90BEA56C2
:10222000FE4F8081882319F460E070E003C00E94B3
:10223000DD26BC018091AD020E94C6271F910F913F
:10224000FF90EF9008951F93162F0E94B810809171
:10225000F002612F0E94C1241F910895EF920F9305
:1022600040E025E002E0B2E0EB2E0E949F0F0E94CA
:10227000E82486E50E9469240F91EF900895EF927B
:102280000F9340E025E002E0EE24E3940E949F0FCC
:102290000E94E8240F91EF9008957F928F929F9271
:1022A000AF92BF92CF92DF92EF92FF920F931F9364
:1022B000DF93CF930F92CDB7DEB7782E87E00E94E1
:1022C00018069C0140E050E060E070E080E090E0A3
:1022D00000EFA02E19EAB12ECC24DD24EE24FF2439
:1022E00000E010E00E941C2B122FF32ED42EC52EDE
:1022F000B62EA72E982EE92E2091870130E040E0DF
:1023000050E060E070E080E090E00DE00E94962CEC
:10231000892E210FE1E0211708F0E0E03F0DF1E008
:102320003F1508F0F0E0FE2EF30EE1E0F31608F0A2
:10233000E0E0FE2B4D0DA1E04D1508F0A0E00F2FC1
:10234000040FE1E0041708F0E0E0AE2B5C0DF1E0D3
:102350005C1508F0F0E01A2F150FE1E0151708F0F2
:10236000E0E0FE2B6B0DA1E06B1508F0A0E0BF2FA5
:10237000B60FE1E0B61708F0E0E0AE2B7A0DF1E021
:102380007A1508F0F0E0A70FE1E0A71708F0E0E009
:10239000FE2B890D91E0891508F090E0F80FE1E03F
:1023A000F81708F0E0E09E2BE80C3F2DA8016B2FFA
:1023B0007A2F8F2F9E0D0DE00E94172C79018A0134
:1023C0008091C5029091C602A091C702B091C80247
:1023D0008E159F05A007B10708F443C08091A8019E
:1023E000882329F18091880190918901A0918A0127
:1023F000B0918B014496A11DB11D8093C5029093AD
:10240000C602A093C702B093C8020E94B9248AE111
:1024100090E00E94470D0E94E8241092A80184E1F8
:102420000E94690680EF809377021092780281E023
:10243000781689F580917802909177028F5F80936A
:1024400078028150891738F184E199830E946906E6
:102450009981933018F096959093770210927802B4
:102460001AC0209188013091890140918A015091D0
:102470008B01281739074A075B0768F481E08093CE
:10248000A8012093C5023093C6024093C70250931F
:10249000C8020E947612B701C8010F90CF91DF9158
:1024A0001F910F91FF90EF90DF90CF90BF90AF9072
:1024B0009F908F907F900895EF92FF920F931F93BC
:1024C00081E00E944D117B018C018091A80188233D
:1024D00041F08BE060E00E94DA24C801B7010E945D
:1024E0003F111F910F91FF90EF9008950E94B92422
:1024F0008091A8018823F9F00E94B92460918C0191
:1025000070E080E090E00E945C0A8FE060E00E9452
:10251000DA248AE091E00E94E82480913702823038
:1025200010F064E601C06BEF8091CA020E94360A87
:102530000E945C1208958AE190E00E94470D60E0DD
:102540000E949C0A0895882361F08150E82FF0E0F2
:10255000E755FE4F908190539093B20210828823EA
:1025600011F40E94761208958091EB02882331F0D5
:10257000F8941092EB0278940E945C120895CF9226
:10258000DF92EF92FF920F931F93CF93DF936C0133
:10259000EB017B0100E010E09C0140E050E0861779
:1025A000970718F597E0EE0CFF1C001F111F9A9576
:1025B000D1F7C801B7010E94F230CA01B9010E94E7
:1025C0007C2E20E030E040E05FE30E94162D0E9468
:1025D000502E709393016093920180E890E0909365
:1025E0009501809394018E0124C087E0220F331F50
:1025F000441F551F8A95D1F7CA01B901A801970157
:102600000E94F230CA01B9010E947C2E20E030E025
:1026100040E05FE30E94162D0E94502E70939501BA
:102620006093940180E890E09093930180939201ED
:102630008601609192017091930185E190E00E9482
:102640002A32609194017091950187E190E00E9497
:102650002A32C801DF91CF911F910F91FF90EF9027
:10266000DF90CF9008950F931F93CF93DF938C014A
:102670000E948E0F85E068EE73E00E942E06EC014A
:1026800086E068EE73E00E942E06BC018C0F9D1F51
:1026900080599140B0F4CE010E94BF12BC019093CA
:1026A00091018093900183E190E00E942A3284E0BE
:1026B0006EE10E94C106C8010E941E078093C202FB
:1026C00003C08AE00E94640FDF91CF911F910F91A8
:1026D00008950F931F93CF93DF938C010E948E0F69
:1026E00085E068EE73E00E942E06EC0186E068EE5D
:1026F00073E00E942E06BC018C0F9D1F855F9140E8
:10270000B0F0CE010E94BF12BC0190938F01809364
:102710008E0181E190E00E942A3284E06EE10E9405
:10272000C106C8010E941E078093C20203C089E04F
:102730000E94640FDF91CF911F910F910895EF9246
:10274000FF920F931F93DF93CF9300D000D00F928F
:10275000CDB7DEB7082F80E090E00E94F631182F49
:102760007E010894E11CF11CC70161E070E045E0C6
:1027700050E00E94E63188E893E10197F1F71B34BD
:1027800099F4002341F080E191E0B7010E9481318A
:10279000009709F485C080E191E0BE016F5F7F4F33
:1027A0000E9481310097B9F080E090E06BE40E94D4
:1027B000143286E090E060E00E94143287E090E0FE
:1027C00060E10E94143280E191E061E070E045E058
:1027D00050E00E940A3288E090E06FE10E941432DB
:1027E00089E090E065E50E9414328AE090E040ECD8
:1027F00053E060E070E00E9422328EE090E061E001
:102800000E9414328FE090E060E00E94143280E178
:1028100090E06EEF0E94143281E190E06CEC71E088
:102820000E942A3283E190E06BE470E00E942A3239
:1028300085E190E060E870E00E942A3287E190E054
:1028400060E870E00E942A3289E190E060E00E9436
:10285000143286E991E06AE170E047E050E00E94BE
:102860000A328DE991E06BE470E047E050E00E94AD
:102870000A328CE790E060E00E9414328DE790E02D
:1028800068E20E9414328EE790E060E00E94143209
:102890008FE790E065E00E9414321092C00278C089
:1028A00088E090E00E94F6318093860189E090E014
:1028B0000E94F631809387018AE090E00E94FE3109
:1028C000609388017093890180938A0190938B01B2
:1028D0008EE090E00E94F63180938C018FE090E0D2
:1028E0000E94F6318093370280E190E00E94F63139
:1028F00080938D0181E190E00E94043290938F01DA
:1029000080938E0183E190E00E94043290939101C4
:102910008093900185E190E00E94043290939301AE
:102920008093920187E190E00E9404329093950198
:102930008093940189E190E00E94F6318093C00277
:1029400086E991E06AE170E047E050E00E94E631FC
:102950008DE991E06BE470E047E050E00E94E631E1
:102960008CE790E00E94F631809338028DE790E08A
:102970000E94F6318093A4018EE790E00E94F63128
:10298000809339028FE790E00E94F6318093A50191
:1029900086E090E00E94F6318093F00287E090E0BC
:1029A0000E94F6318093BE02809188019091890146
:1029B000A0918A01B0918B018093C5029093C602C9
:1029C000A093C702B093C8028091A6019091A7017D
:1029D0000E941E078093C202809137028093CA0230
:1029E00080E0609196010E94EA26609197017091C3
:1029F000980180E00E94F9266091990170919A01F6
:102A000080E00E94162760919B0170919C0180E0FC
:102A10000E94352781E060919D010E94EA26609125
:102A20009E0170919F0181E00E94F9266091A001B2
:102A30007091A10181E00E9416276091A20170911E
:102A4000A30181E00E9435270E94300981E0809334
:102A5000B7020E941909809138020E94EB2A0F9058
:102A60000F900F900F900F90CF91DF911F910F91CA
:102A7000FF90EF9008951F93CF93DF9381EF92E043
:102A800062E00E94F92A8823C9F18091F102843022
:102A9000A9F58091F30290E09695982F8827979555
:102AA00087952091F40230E0822B932B64E170E053
:102AB0000E94DE306C33710518F4C0E0D0E007C02E
:102AC000EB01EC97C53BD10510F0C4EBD0E01091C1
:102AD000F2020E94DD26A0E0B0E09E0140E050E05E
:102AE000BC01CD010E94B33024EB30E040E050E067
:102AF0000E94F230812FB9010E94C627DF91CF9149
:102B00001F9108958091C9028823A9F0F89410922A
:102B1000C90278946091A6017091A7018091370253
:102B200040E00E942C0B8093CA02809138028330CF
:102B300011F40E943B1508951F938FE40E94852A8B
:102B4000882391F08091D3029091D4028C5E9440BE
:102B500058F48091350387FF07C08091340381705A
:102B600080933B0211E001C010E08091390288237C
:102B700059F08091D3029091D402855A914020F06F
:102B800085E191E00E94BC29812F1F9108952F9229
:102B90003F924F925F926F927F928F929F92AF92ED
:102BA000BF92CF92DF92EF92FF920F931F93DF932A
:102BB000CF93CDB7DEB728970FB6F894DEBF0FBE20
:102BC000CDBF69A07AA08BA09CA06FA978AD89AD7C
:102BD0009AAD0E947E2E20E836E948E15BE40E942F
:102BE000E32D5B016C01C401B301A60195010E94B4
:102BF000162D20E030E040E05FE30E94F32F29E350
:102C00003AEF4EE85CE30E94F32F0E94E02D20E0B3
:102C100032E649ED57E40E94F32F7B018C016BA94A
:102C20007CA98DA99EA90E947E2E20E836E948E164
:102C30005BE40E94E32D9B01AC016D8D7E8D8F8D39
:102C400098A10E94152D9B01AC01C801B7010E94FB
:102C5000F32F1B012C01C401B301A60195010E94B1
:102C6000152D20E032E649ED57E40E94F32F5B0179
:102C70006C01C201B101A60195010E94892D21EECE
:102C80003EE245E652E40E94F32F20E030E044E3C8
:102C900053E40E94162D20E030E044EB53E40E9400
:102CA000C02E7B018C0137014801C801B70120E02B
:102CB00030E044EB53E40E94E82F181654F4C801A6
:102CC000B70120E030E044EB53E40E94152D3B01B6
:102CD0004C01C201B101A20191010E94F32F7B01BD
:102CE0008C01C601B501A60195010E94F32F9B013D
:102CF000AC01C801B7010E94162D0E945A306983A9
:102D00007A838B839C836D827E828F8298862981D1
:102D10003A814B815C816D817E818F819885289677
:102D20000FB6F894DEBF0FBECDBFCF91DF911F91DC
:102D30000F91FF90EF90DF90CF90BF90AF909F905A
:102D40008F907F906F905F904F903F902F9008955D
:102D5000AF92BF92CF92DF92EF92FF920F931F93A9
:102D6000DF93CF93CDB7DEB728970FB6F894DEBFC9
:102D70000FBECDBF0E949C15882309F485C18091A8
:102D8000B702882309F463C08091340383FF7CC1B8
:102D9000A0901003B0901103C0901203D0901303C1
:102DA000C601B5010E947E2E20E836E948E15BE4C9
:102DB0000E94E32D6093D5027093D6028093D702D0
:102DC0009093D802E0901403F0901503009116033D
:102DD00010911703C801B7010E947E2E20E836E942
:102DE00048E15BE40E94E32D6093D9027093DA021C
:102DF0008093DB029093DC02A092DD02B092DE02AF
:102E0000C092DF02D092E002E092E102F092E20290
:102E10000093E3021093E402809118039091190348
:102E2000A0911A03B0911B038093E5029093E602F0
:102E3000A093E702B093E80280912F0390913003B2
:102E40009093EA028093E9021092B7021DC18DB7F8
:102E50009EB783970FB6F8949EBF0FBE8DBF2DB758
:102E60003EB72F5F3F4FD901E5EDF2E086E10190DB
:102E70000D928150E1F7D9015696E2EFF2E08DE034
:102E800001900D928150E1F70E94C71529833A8382
:102E90004B835C836D837E838F839887ABECB2E03A
:102EA000FE01319688E001900D928150E1F760912A
:102EB000FA027091FB028091FC029091FD02209138
:102EC000E5023091E6024091E7025091E802621B70
:102ED000730B840B950B0E947E2E20E030E04AE7B6
:102EE00054E40E94E32D5B016C016093B80270937F
:102EF000B9028093BA029093BB02E090CB02F090AB
:102F0000CC020091CD021091CE028DB79EB7839670
:102F10000FB6F8949EBF0FBE8DBFC601B501A801C4
:102F200097010E94892D21EE3EE245E652E40E947F
:102F3000F32F0E944B2E7093AF026093AE02C80134
:102F4000B70120E030E040E850E40E94DC2D882307
:102F500004F56091E9027091EA02882777FD809577
:102F6000982F0E947E2E6093CF027093D0028093A0
:102F7000D1029093D202C601B50120E030E040E4D6
:102F800050E40E94DC2D882324F41092AF021092AA
:102F9000AE026091E9027091EA02882777FD809580
:102FA000982F0E947E2E9B01AC016091CF02709100
:102FB000D0028091D1029091D2020E94152D20E082
:102FC00030E044EB53E40E94162D20E030E044EB67
:102FD00052E40E94162D20E030E044EB53E40E94BE
:102FE000C02E9B01AC01CA01B9010E944B2ECB013E
:102FF0007093B4026093B30221E06936720734F033
:10300000885691409093B4028093B3028091AE02AF
:103010009091AF0297FF04C01092AF021092AE02DF
:103020008091AE029091AF02853B910534F084EB24
:1030300090E09093AF028093AE028091B3029091A2
:10304000B402843B910594F0845B90409093B40269
:103050008093B30284EB90E02091AE023091AF02F6
:10306000821B930B9093AF028093AE026091B302E8
:103070007091B40280E00E943E096091AE027091AE
:10308000AF0281E00E943E0980913A02882309F450
:1030900043C18091B702882309F03EC18091A80105
:1030A000882309F439C18091B602882321F0109257
:1030B000B6020E94B92480913A02823009F4A8C075
:1030C000833009F4E6C0813009F026C16091E9023D
:1030D0007091EA02882777FD8095982F40E023E0E1
:1030E00000E0EE240E949F0F9C0180E060E040E23F
:1030F00051E00FED0E94200CE090CB02F090CC024A
:103100000091CD021091CE02C801B70120E030E05D
:1031100040E251E40E94DC2D882384F4C801B70109
:1031200020E030E040E251E40E94F32F0E94502E54
:1031300040E023E001E0EE24E39408C0C801B701B9
:103140000E94502E40E023E000E0EE240E949F0FFA
:103150009C0188E060E045E251E00DE60E94200C11
:103160006091CF027091D0028091D1029091D202F1
:103170000E94502E40E023E000E0EE240E949F0FCA
:103180009C0180E061E04AE251E00FED0E94200CDA
:103190006091B8027091B9028091BA029091BB021D
:1031A0000E94502E41E022E000E00E949F0F9C010F
:1031B00088E061E04FE251E00DE60E94200C609152
:1031C000B3027091B402882777FD8095982F40E074
:1031D00023E000E00E949F0F9C0180E062E044E356
:1031E00051E00FED0E94200C6091AE027091AF0291
:1031F000882777FD8095982F40E023E000E00E942B
:103200009F0F9C0188E062E049E351E00FED82C02E
:103210006091F2027091F3028091F4029091F502B4
:1032200040E02BE007E057E0E52E0E949F0F9C0155
:1032300080E060E04EE351E000E00E94200C6091ED
:10324000F6027091F7028091F8029091F90240E045
:103250002BE007E00E949F0F9C0180E061E044E4C6
:1032600051E000E00E94200C6091FA027091FB0294
:103270008091FC029091FD0241E02BE003E0EE24FE
:10328000E3940E949F0F9C0180E062E04AE451E0D9
:1032900040C06091DD027091DE028091DF0290916A
:1032A000E00240E02BE007E037E0E32E0E949F0FB2
:1032B0009C0180E060E041E551E000E00E94200CCC
:1032C0006091E1027091E2028091E3029091E40248
:1032D00040E02BE007E00E949F0F9C0180E061E04E
:1032E00047E551E000E00E94200C6091E5027091FA
:1032F000E6028091E7029091E80241E02BE003E0D2
:10330000EE24E3940E949F0F9C0180E062E04DE573
:1033100051E000E00E94200C0E94F30B28960FB6AB
:10332000F894DEBF0FBECDBFCF91DF911F910F91FB
:10333000FF90EF90DF90CF90BF90AF900895809175
:10334000AC02882381F0F8941092AC0278948091BA
:103350003802823011F40E94A81680913A0284301B
:1033600011F40E94E10808950E9482150E949F199D
:103370000E94290880913802813011F40E9462096C
:1033800008950E94B41980E00E944D1180E20E94CD
:103390004926882321F48091A801882311F41092F2
:1033A000A90108952F923F924F925F926F927F9260
:1033B0008F929F92AF92BF92CF92DF92EF92FF9245
:1033C0000F931F93DF93CF93CDB7DEB727970FB639
:1033D000F894DEBF0FBECDBF962ED72E782E692E65
:1033E00029833A834B835C8317012801CD82BF82F6
:1033F000AE82B82C8C2D61E00E94DA24692D7D2DDF
:10340000872D962D2E813F81F90109951EC000D090
:10341000EDB7FEB71182B282692D7D2D872D962DD5
:1034200029813A814B815C8182017101CD80AA247E
:10343000A3948E809F800E946A0C962ED72E782EA1
:10344000692E0F900F900E94C11980E20E943926C8
:10345000882321F48091A9018823C9F60E94B92408
:10346000E9EAF1E001900020E9F73197E95AF140EB
:103470008E2F0E94A312692D7D2D872D962D2796C4
:103480000FB6F894DEBF0FBECDBFCF91DF911F9175
:103490000F91FF90EF90DF90CF90BF90AF909F90F3
:1034A0008F907F906F905F904F903F902F900895F6
:1034B0008F92AF92BF92CF92EF92FF920F931F9392
:1034C00084E40E94D70E6091A50170E080E090E056
:1034D00020E030E040E050E0A6E0EA2EF12C012DA3
:1034E000112DF3E0CF2EEAE3AE2EECE0BE2E8824C1
:1034F0000E94D2199B01AC018091A50190E0A0E04F
:10350000B0E0281739074A075B07C1F02093A501EF
:103510008FE790E0622F0E94143284E06EE10E94F7
:10352000C106E091A501F0E0EE0FFF1FEE0FFF1FB7
:10353000EA59FE4F808191810E94972989EA91E0A2
:103540000E94EB0C1F910F91FF90EF90CF90BF90D6
:10355000AF908F9008958F92AF92BF92CF92EF92DB
:10356000FF920F931F9389E20E94D70E6091390258
:1035700070E080E090E020E030E040E050E0F1E0FA
:10358000EF2EF12C012D112DE3E0CE2EB2E5AB2E66
:10359000BEE0BB2E88240E94D2199B01AC01809111
:1035A000390290E0A0E0B0E0281739074A075B072E
:1035B00059F0209339028EE790E0622F0E94143276
:1035C00084E06EE10E94C10689EA91E00E94EB0C62
:1035D0001F910F91FF90EF90CF90BF90AF908F9081
:1035E00008958F92AF92BF92CF92EF92FF920F9376
:1035F0001F938AE20E94D70E6091A40170E080E0E0
:1036000090E020E030E040E050E0E4E6EE2EF12CE7
:10361000012D112DB7E0CB2EA8EBAA2EA0E1BA2EDA
:10362000882483940E94D2199B01AC018091A4014B
:1036300090E0A0E0B0E0281739074A075B0759F08F
:103640002093A4018DE790E0622F0E94143284E061
:103650006EE10E94C10689EA91E00E94EB0C1F9185
:103660000F91FF90EF90CF90BF90AF908F90089503
:1036700080913802823039F0833041F0813041F45A
:103680000E94F11A08950E94AB1A08950E94581AD8
:1036900008958F92AF92BF92CF92EF92FF920F93C5
:1036A0001F9387E20E94D70E6091380270E080E09D
:1036B00090E020E030E040E050E0B3E0EB2EF12C71
:1036C000012D112DA3E0CA2EFAE6AF2EFEE0BF2E8B
:1036D00088240E94D2199B01AC018091380290E0AD
:1036E000A0E0B0E0281739074A075B0709F440C09B
:1036F000F894622F2093380278948CE790E00E942F
:10370000143284E06EE10E94C106809138020E946A
:10371000EB2A81E08093B70210923C0210923D02A6
:1037200010923E0210923F0210924002109241020B
:1037300010924202109243020E9430098091380296
:10374000882321F420E044EF51E00BC00E94792649
:103750000DC0FA013197F1F70197D9F72F5F2230A9
:1037600019F080ED97E0F5CF0E94C0270E9419095B
:1037700089EA91E00E94EB0C1F910F91FF90EF906E
:10378000CF90BF90AF908F9008958F92AF92BF92DD
:10379000CF92EF92FF920F931F9385E10E94D70E75
:1037A0006091870170E080E090E020E030E040E050
:1037B00050E0A8ECEA2EF12C012D112DF4E0CF2ED3
:1037C000EEE2AE2EE1E1BE2E882483940E94D2194F
:1037D0009B01AC018091870190E0A0E0B0E0281748
:1037E00039074A075B0759F02093870189E090E089
:1037F000622F0E94143284E06EE10E94C10689EAC1
:1038000091E00E94EB0C1F910F91FF90EF90CF90F1
:10381000BF90AF908F9008958F92AF92BF92CF924A
:10382000EF92FF920F931F9383E10E94D70E609156
:1038300088017091890180918A0190918B0126E223
:1038400032E040E050E0F8E7EF2EF5E0FF2E012DEA
:10385000112DE4E0CE2EBEE2AB2EB1E1BB2E8824CA
:1038600083940E94D219AB01BC0180918801909190
:103870008901A0918A01B0918B01481759076A0705
:103880007B0701F1409388015093890160938A017D
:1038900070938B018AE090E00E942232809188012F
:1038A00090918901A0918A01B0918B018093C5020A
:1038B0009093C602A093C702B093C80284E06EE161
:1038C0000E94C10689EA91E00E94EB0C1F910F91C2
:1038D000FF90EF90CF90BF90AF908F9008958F9210
:1038E000AF92BF92CF92EF92FF920F931F938DE012
:1038F0000E94D70E80E061E00E94DA248EE090E022
:103900000E94470D0E94E8246091860170E080E0EB
:1039100090E020E030E040E050E0EFE1EE2EF12CCE
:10392000012D112DB6E0CB2EABEBAA2EADE0BA2EB9
:10393000882483940E94D2199B01AC018091860156
:1039400090E0A0E0B0E0281739074A075B0791F044
:103950002093860188E090E0622F0E94143284E078
:103960006EE10E94C10680918601882319F41092AD
:1039700036022F9889EA91E00E94EB0C1F910F917B
:10398000FF90EF90CF90BF90AF908F9008958F925F
:10399000AF92BF92CF92EF92FF920F931F9388E363
:1039A0000E94D70E82E061E00E94DA248CE090E071
:1039B0000E94470D0E94E82480E091E00E94E824E4
:1039C0006091BE0270E080E090E020E030E040E0F6
:1039D00050E0BEE1EB2EF12C012D112DABE0CA2EF3
:1039E000F3E2AF2EF1E1BF2E88240E94D2199B0191
:1039F000AC018091BE0290E0A0E0B0E0281739074A
:103A00004A075B0759F02093BE0287E090E0622FDF
:103A10000E94143284E06EE10E94C10689EA91E0BE
:103A20000E94EB0C1F910F91FF90EF90CF90BF90F1
:103A3000AF908F9008958F92AF92BF92CF92DF9206
:103A4000EF92FF920F931F930E949A08D82E109125
:103A5000AD020E94DD26BC0176956795812F0E94FC
:103A6000C6272091C00230E08091AD0290E0FC01B9
:103A700013E0EE0FFF1F1A95E1F7E81BF90BEA566A
:103A8000FE4F6581768180E090E0F901EE0FFF1F27
:103A9000E20FF31FEE0FFF1FEE0FFF1FE255FE4F69
:103AA0002085318540E050E0E284F38400E010E0BE
:103AB000F5E0CF2EE1E8AE2EE0E1BE2E882483941F
:103AC0000E94D219AB01BC018091AD02282F30E0D9
:103AD000F90113E0EE0FFF1F1A95E1F7E21BF30B5C
:103AE000EA56FE4F85819681A0E0B0E0481759075D
:103AF0006A077B07B1F05683458381E390E0289FF6
:103B0000B001299F700D389F700D1124665E7F4FA4
:103B1000CF0147E050E00E940A3284E06EE10E944B
:103B2000C1068D2D0E941A0D1F910F91FF90EF90ED
:103B3000DF90CF90BF90AF908F90089584E20E9465
:103B4000D70E0E941B1D089580E20E94D70E0E948E
:103B50001B1D08958F92AF92BF92CF92DF92EF928A
:103B6000FF920F931F930E949A08D82E8091AD0266
:103B700060E070E00E94C6272091C00230E0809192
:103B8000AD0290E0FC0103E0EE0FFF1F0A95E1F7A4
:103B9000E81BF90BEA56FE4F6181728180E090E0EC
:103BA000F901EE0FFF1FE20FF31FEE0FFF1FEE0FE5
:103BB000FF1FDF01A255BE4F2D913C9140E050E028
:103BC000E055FE4FE080F18000E010E0E6E0CE2E10
:103BD000B7EFAB2EB0E1BB2E882483940E94D2199C
:103BE000AB01BC018091AD02282F30E0F901A3E0C8
:103BF000EE0FFF1FAA95E1F7E21BF30BEA56FE4F0B
:103C000081819281A0E0B0E0481759076A077B07DD
:103C100041F15283418381E390E0289FB001299FC5
:103C2000700D389F700D1124665E7F4FCF0147E005
:103C300050E00E940A328091AD02282F30E0F90155
:103C400093E0EE0FFF1F9A95E1F7E21BF30BEA56A4
:103C5000FE4F658176810E94352784E06EE10E94E7
:103C6000C1068D2D0E941A0D1F910F91FF90EF90AC
:103C7000DF90CF90BF90AF908F90089583E20E9425
:103C8000D70E0E94AA1D08958FE10E94D70E0E94B0
:103C9000AA1D08958F92AF92BF92CF92DF92EF92BA
:103CA000FF920F931F930E949A08D82E1091AD0295
:103CB0000E94DD26BC01812F0E94C6272091C002F0
:103CC00030E08091AD0290E0FC0103E0EE0FFF1FB9
:103CD0000A95E1F7E81BF90BEA56FE4F6381748100
:103CE00080E090E0F901EE0FFF1FE20FF31FEE0FEF
:103CF000FF1FEE0FFF1FDF01AE54BE4F2D913C9111
:103D000040E050E0E255FE4FE680F78000E010E032
:103D1000E6E0CE2EB5ECAB2EB0E1BB2E882483942A
:103D20000E94D219AB01BC018091AD02282F30E076
:103D3000F901A3E0EE0FFF1FAA95E1F7E21BF30BD9
:103D4000EA56FE4F83819481A0E0B0E048175907FE
:103D50006A077B0741F15483438381E390E0289F06
:103D6000B001299F700D389F700D1124665E7F4F42
:103D7000CF0147E050E00E940A328091AD02282F27
:103D800030E0F90193E0EE0FFF1F9A95E1F7E21B97
:103D9000F30BEA56FE4F658176810E94352784E059
:103DA0006EE10E94C1068D2D0E941A0D1F910F9188
:103DB000FF90EF90DF90CF90BF90AF908F900895DD
:103DC00082E20E94D70E0E944A1E08958EE10E9450
:103DD000D70E0E944A1E08958F92AF92BF92CF9243
:103DE000DF92EF92FF920F931F930E949A08D82EB2
:103DF0008091AD0290E0FC01B3E0EE0FFF1FBA9599
:103E0000E1F7E81BF90BEA56FE4F608170E080E0B5
:103E100090E020E030E040E050E0A1E0EA2EF12C1C
:103E2000012D112DF6E0CF2EECEAAE2EEDE0BE2EE8
:103E300088240E94D2199B01AC016091AD02862FAB
:103E400090E0FC0173E0EE0FFF1F7A95E1F7E81BAD
:103E5000F90BEA56FE4F808190E0A0E0B0E0281711
:103E600039074A075B0729F12083862F622F0E94BA
:103E7000EA262091AD0230E0C90143E0880F991F86
:103E80004A95E1F7821B930B41E350E0249FB00178
:103E9000259F700D349F700D1124665E7F4F8A56EA
:103EA0009E4F47E050E00E940A3284E06EE10E949B
:103EB000C1068D2D0E941A0D1F910F91FF90EF905A
:103EC000DF90CF90BF90AF908F90089581E20E94D5
:103ED000D70E0E94EC1E08958DE10E94D70E0E941D
:103EE000EC1E08958F92AF92BF92CF92EF92FF9205
:103EF0000F931F938CE10E94D70E88E061E00E942F
:103F0000DA246091C00270E080E090E020E030E0D0
:103F100040E050E0A1E0EA2EF12C012D112DF5E05A
:103F2000CF2EE4E9AE2EEDE0BE2E88240E94D219F9
:103F30009B01AC018091C00290E0A0E0B0E02817A6
:103F400039074A075B0799F0F8942093C00289E18A
:103F500090E0622F0E9414328091C0020E94D80922
:103F60000E947926789484E06EE10E94C10689EA75
:103F700091E00E94EB0C1F910F91FF90EF90CF907A
:103F8000BF90AF908F9008958F92AF92BF92CF92D3
:103F9000EF92FF920F931F9380E00E94D70E6091E3
:103FA0008D0170E080E090E020E030E040E050E003
:103FB000F2E0EF2EF12C012D112DE3E0CE2EB5E72E
:103FC000AB2EBDE0BB2E88240E94D2197B018C0150
:103FD00080E190E00E94F63180938D0190E0A0E0B6
:103FE000B0E0E816F9060A071B0759F0E0928D01C8
:103FF00080E190E06E2D0E94143284E06EE10E9418
:10400000C10689EA91E00E94EB0C1F910F91FF908D
:10401000EF90CF90BF90AF908F9008958F92AF9216
:10402000BF92CF92EF92FF920F931F9386E00E9470
:10403000D70E60918C0170E080E090E021E030E0EC
:1040400040E050E0E7E0EE2EF12C012D112DB3E021
:10405000CB2EACE5AA2EAAE0BA2E88240E94D21953
:104060009B01AC0180918C0190E0A0E0B0E02817AA
:1040700039074A075B0751F48091EF0290E0A0E016
:10408000B0E0281739074A075B07F9F020938C0145
:104090002093EF028EE090E0622F0E94143284E0C1
:1040A0006EE10E94C10680918C010E94860580917C
:1040B000A901882351F460E00E94DA2460918C0108
:1040C00070E080E090E00E945C0A89EA91E00E9442
:1040D000EB0C1F910F91FF90EF90CF90BF90AF909E
:1040E0008F9008958F92AF92BF92CF92EF92FF92EE
:1040F0000F931F9385E00E94D70E6091370270E006
:1041000080E090E020E030E040E050E0B2E0EB2ED4
:10411000F12C012D112DA3E0CA2EF9E8AF2EFEE0FF
:10412000BF2E88240E94D2199B01AC0180913702D6
:1041300090E0A0E0B0E0281739074A075B0711F1CB
:10414000F894209337028FE090E0622F0E9414329F
:1041500084E06EE10E94C106809137020E94A005B2
:10416000982F8093CA028091A901882351F48091ED
:104170003702823010F064E601C06BEF892F0E9495
:10418000360A789489EA91E00E94EB0C1F910F9116
:10419000FF90EF90CF90BF90AF908F9008950F93C6
:1041A0001F93CF93DF93EC01062F142F8091AA0168
:1041B000882309F590913802892F81508330D8F4F3
:1041C0000F5F913029F4FE01E00FF11D83E480833D
:1041D00080913802823031F4FE01E00FF11D89E256
:1041E00080830F5F80913802833029F4FE01E00F55
:1041F000F11D82E380830E94B92480E061E00E9487
:10420000DA248CEF0E946924CE01612F402F0E9496
:104210001C0F2AC080E40E942326882329F480E40E
:104220000E942E26882351F0112311F4102F01C073
:104230001150CE01612F402F0E941C0F80E80E9478
:104240002326882329F480E80E942E26882351F013
:10425000101710F010E001C01F5FCE01612F402F3A
:104260000E941C0F0E94C11980E20E9439268823F7
:1042700021F48091A901882369F60E94B9248091D4
:10428000A9018823E1F0E9EAF1E0DF010D900020C7
:10429000E9F71197AE1BBF0B112369F081E0809302
:1042A000B202EA2FF0E0E755FE4F105D1083118255
:1042B0000E94690606C08A2F0E94A31202C00E94B3
:1042C0007612DF91CF911F910F910895DF93CF93D5
:1042D00000D000D00F92CDB7DEB7DE011196E6EC2C
:1042E000F1E085E001900D928150E1F7CE01019659
:1042F00064E04091B2020E94CF2089EA91E00E94DE
:10430000EB0C0F900F900F900F900F90CF91DF91CB
:104310000895DF93CF9300D00F92CDB7DEB7DE01C3
:104320001196EBECF1E083E001900D928150E1F702
:10433000CE01019662E04091B2020E94CF2089EA4C
:1043400091E00E94EB0C0F900F900F90CF91DF91B6
:104350000895DF93CF9300D00F92CDB7DEB7DE0183
:104360001196EEECF1E083E001900D928150E1F7BF
:10437000CE01019662E04091B2020E94CF2089EA0C
:1043800091E00E94EB0C0F900F900F90CF91DF9176
:104390000895DF93CF9300D000D00F92CDB7DEB752
:1043A000DE011196E1EDF1E085E001900D92815082
:1043B000E1F7CE01019664E04091B2020E94CF2065
:1043C00081E08093AD0289EA91E00E94EB0C0F90AE
:1043D0000F900F900F900F90CF91DF910895DF9382
:1043E000CF9300D000D00F92CDB7DEB7DE0111968B
:1043F000E6EDF1E085E001900D928150E1F7CE010C
:10440000019664E04091B2020E94CF201092AD026A
:1044100089EA91E00E94EB0C0F900F900F900F90A3
:104420000F90CF91DF910895DF93CF9300D000D00C
:10443000CDB7DEB784E089838CE18A838FE38B83F9
:1044400080E48C83CE01019663E04091B2020E9429
:10445000CF2089EA91E00E94EB0C0F900F900F9013
:104460000F90CF91DF910895DF93CF9300D00F92FB
:10447000CDB7DEB7DE011196EEEDF1E083E00190FD
:104480000D928150E1F7CE01019662E04091B202B7
:104490000E94CF2089EA91E00E94EB0C0F900F90D0
:1044A0000F90CF91DF910895DF93CF93CDB7DEB713
:1044B0002B970FB6F894DEBF0FBECDBFDE0111966D
:1044C000E1EEF1E08BE001900D928150E1F789EA95
:1044D00091E064E671E00E948A31CE01019668E0C5
:1044E0004091B2020E94CF2089EA91E00E94EB0C39
:1044F0002B960FB6F894DEBF0FBECDBFCF91DF91E4
:10450000089502C00E94C11980E20E9439268823C2
:1045100021F48091A9018823A9F70E94B9248091F0
:10452000A901882319F40E94761203C081E00E9439
:1045300069068091A901811181E0089581E30E94BB
:10454000D70E80E061E00E94DA248BE390E00E94C5
:10455000470D0E94E82480E062E00E94DA248CE3A8
:1045600090E00E94470D0E94E8240E94E10884E048
:1045700080933A028093B2020E948122882339F00C
:10458000E9EAF1E001900020E9F7329710821092F9
:104590003A0289EA91E00E94EB0C0895CF93DF93F1
:1045A000E9EAF1E001900020E9F73197E95AF1409A
:1045B000E150CE2FD0E0C755DE4F888180538093E5
:1045C0003A028093B20281E08093B60280E390E0E9
:1045D0000E94470D0E94E8240E94812281111882C6
:1045E00010923A0289EA91E00E94EB0CDF91CF91A0
:1045F00008950F931F93DF93CF93CDB7DEB76497E2
:104600000FB6F894DEBF0FBECDBF86E30E94D70E73
:1046100088E090E00E94470DBC018E010F5F1F4FA4
:10462000C8010E948A318AE090E00E94470DBC01D7
:10463000C8010E947631C80161E00E949C0A8BE0AB
:1046400090E00E94470D62E00E949C0A0E94812235
:10465000882359F08091A6019091A7010E943313FD
:104660001092A9010E94761204C089EA91E00E948A
:10467000EB0C64960FB6F894DEBF0FBECDBFCF91A2
:10468000DF911F910F9108950F931F93DF93CF93A5
:10469000CDB7DEB764970FB6F894DEBF0FBECDBFBF
:1046A00085E30E94D70E88E090E00E94470DBC0190
:1046B0008E010F5F1F4FC8010E948A3189E090E090
:1046C0000E94470DBC01C8010E947631C80161E01B
:1046D0000E949C0A8BE090E00E94470D62E00E94DD
:1046E0009C0A0E948122882359F08091A601909112
:1046F000A7010E9469131092A9010E94761204C0BA
:1047000089EA91E00E94EB0C64960FB6F894DEBF44
:104710000FBECDBFCF91DF911F910F9108958F9262
:104720009F92AF92CF92DF92EF92FF920F931F93DF
:1047300088EE93E024EF31E0F9013197F1F701972A
:10474000D9F7239A2B9887B18F7387B9579886B179
:1047500090E0807C09F091E0892F0E949F134F998F
:1047600004C0369902C00E94FE0881B18F6181B9F0
:1047700084B1876184B980918C010E948605809103
:104780008C018093EF0213980E94FF0585E085BDA0
:1047900080916E00816080936E0083E08093B10011
:1047A000809170008160809370008AB1837F8AB9A4
:1047B000809169008A6080936900809137020E942D
:1047C000A0058AB180638AB980913802882311F0EC
:1047D0000E9479268091F0026091BE0240E020E0C4
:1047E0000E940A250E94BE058DE99AE066E00E94BB
:1047F0009C240E94A80E82E06EE10E94C10678947B
:1048000080918D018E3F21F410928D010E94C41F72
:104810001092A9010E947612DD24D3940E94B41252
:104820000E94DE0B0E94B4198091A8018823B1F385
:1048300080E20E943926882321F0D092B2020E94A1
:10484000542200D060918C0170E080E090E0EDB7E0
:10485000FEB7D182128221E030E040E050E0F7E084
:10486000EF2EF12C012D112DCC24AA24ECE58E2E57
:10487000EAE09E2E0E946A0C0F900F9080918C01AE
:10488000681761F260938C01862F0E948605C6CF5F
:1048900028B1982F9F70922B98B998B1806F982368
:1048A00098B9459A8DE08A95F1F7459888EC8A95F4
:1048B000F1F708951F93182F82958F700E94482456
:1048C000812F0E9448241F91089544980E945A24E1
:1048D0000895449A0E945A240895EF92FF920F93EC
:1048E0001F93CF93DF93182F7B0188E20E946524EA
:1048F000012F10E083E0000F111F8A95E1F7C0E05F
:10490000D0E09E01200F822F80640E946524F70171
:10491000EC0FFD1FE4918E2F0E9469242196C83070
:10492000D10579F789E20E946524DF91CF911F912B
:104930000F91FF90EF900895EF92FF920F931F93C6
:10494000CF93DF937C01062F10E0C0E0D0E008C0D9
:10495000B7016C0F7D1F812F0E946D241F5F289669
:104960001017B0F3DF91CF911F910F91FF90EF904F
:10497000089581E00E94652480E197E20197F1F7B4
:1049800008950F931F93162F813011F400E501C095
:1049900004E589E20E946524812F8F7080670E9460
:1049A000652412951370802F812B0E9465241F911E
:1049B0000F910895813108F080E0643008F060E0E4
:1049C0006295607F680F862F80680E946524089535
:1049D0000F931F93CF93DF93EC0100E010E00FC023
:1049E0008A3051F4133010F010E001C01F5F80E0F6
:1049F000612F0E94DA2402C00E9469240F5FFE0129
:104A0000E00FF11D8081882359F7DF91CF911F912D
:104A10000F910895CF92DF92EF92FF920F931F9321
:104A2000582F162FC42E022F279A3D9A3C9A87B1F1
:104A30008F6087B9459880E991E024EF31E0F90172
:104A40003197F1F70197D9F7513039F4EDE1FE2EA6
:104A50007CE6D72E60E5E62E06C055E1F52E4EE643
:104A6000D42E34E5E32E449883E00E94482480E16C
:104A700097E20197F1F783E30E94482482E30E94C2
:104A8000652489E20E9465248F2D0E946524812F70
:104A90008F7080670E946524129513708E2D812B74
:104AA0000E9465248D2D0E94652488E20E94652461
:104AB00001700C608C2D90E081709070880F991FB0
:104AC000802B0E9465240E94B92486E00E94652400
:104AD0001F910F91FF90EF90DF90CF9008951F925C
:104AE0000F920FB60F9211242F933F938F939F93A2
:104AF0008DE386BD26B189B13091880390E080783E
:104B000090709595879595958795207C282B209575
:104B10002327809190028223809580939002909128
:104B20008F029223982790938F028223892390915A
:104B300088039827909388032091ED029091880331
:104B40008923822B8093ED028091ED02807E51F0CB
:104B50001092BD021092BC0288EE93E09093210265
:104B60008093200280918803807E49F482E38093C1
:104B70008E0284E18093C30286E08093B10280912B
:104B80008E02815080938E02882361F48091C3024B
:104B900080938E029091C10280918803807E892B40
:104BA0008093C10280918D02815080938D02882371
:104BB00031F482E380938D0281E08093EB02809157
:104BC0008C02815080938C02882331F484E180939D
:104BD0008C0281E08093BF0280918B028150809390
:104BE0008B02882331F482E080938B0281E08093F2
:104BF000C90280918A02815080938A02882331F40D
:104C00008AE080938A0281E08093AC028091200246
:104C10009091210201979093210280932002892B89
:104C200049F488EE93E0909321028093200281E082
:104C3000809387039F918F913F912F910F900FBE8B
:104C40000F901F901895F8949091ED028923909100
:104C5000ED0298279093ED0278940895F89490913E
:104C6000C10289239091C10298279093C102789440
:104C70000895F89490918803F8942091ED0290950E
:104C8000892382239091ED0298279093ED027894E6
:104C90000895982FF8948091C10298238091C102C1
:104CA00089278093C1027894F8948091ED0289233A
:104CB0009091ED0298279093ED02789408958823BF
:104CC000B9F08091B102882341F0F8948091B1024B
:104CD00081508093B102789408958091C30284300A
:104CE00038F0F8948091C30282508093C302789484
:104CF000089580916F008D7F80936F00E091C002D6
:104D0000EE2309F051C0809181008C7F8093810057
:104D10008091810084608093810080E18093890389
:104D200080E2809395031092A2031092A103F0E019
:104D300083E0EE0FFF1F8A95E1F7EE5DFD4F2681C0
:104D4000378140E050E060E07DE281E391E00E9445
:104D5000F230CA01B90124E130E040E050E00E94A5
:104D6000B3300E947C2E2FE632E143E85AE30E94E2
:104D7000F32F0E94502EAB017093A4036093A30302
:104D80003091880020918900922F80E0830F911D3F
:104D9000840F951F909389008093880080916F0005
:104DA000826080936F000895809181008B7F809353
:104DB0008100809181008360AECFE091C002F0E07D
:104DC00093E0EE0FFF1F9A95E1F7EA5DFD4F8081BA
:104DD0009181089590E0FC01EE0FFF1FE80FF91F8D
:104DE000EE0FFF1FEE0FFF1FE757FC4F617063834D
:104DF000089590E0DC01AA0FBB1FA80FB91FAA0FEE
:104E0000BB1FAA0FBB1FA357BC4FE091C002F0E02D
:104E100043E0EE0FFF1F4A95E1F7EC5DFD4F808107
:104E20009181860F971F8D939C93089590E0DC01EC
:104E3000AA0FBB1FA80FB91FAA0FBB1FAA0FBB1F2A
:104E4000A757BC4FE091C002F0E083E0EE0FFF1FD8
:104E50008A95E1F7EE5DFD4F80819181861B970B6E
:104E600017969C938E93169708954F925F926F9228
:104E70007F928F929F92AF92BF92CF92DF92EF92EA
:104E8000FF920F931F937B0190E0E9E8F3E09C0110
:104E9000220F331F280F391F4901880C991C880CD9
:104EA000991C8E0E9F1ED4011B96FC92EE921A97AF
:104EB0002F5F3F4F220F331F220F331FE20FF31FCD
:104EC000A080B18016966D917C9117976A197B0925
:104ED00080E090E00E947C2E20E030E040E05FE344
:104EE0000E94F32F2B013C0100E010E0C801B70144
:104EF0000E947C2E7B018C01E091C002F0E033E047
:104F0000EE0FFF1F3A95E1F7EA5DFD4F6081718179
:104F100080E090E00E947C2E20E030E040E05FEBFB
:104F20000E94F32F9B01AC01C801B7010E94162D0E
:104F30009B01AC01C301B2010E94162D7B018C01C3
:104F4000CC24DD24C601B5010E947C2E9B01AC015E
:104F5000C801B7010E94162D0E94502EF4017187DE
:104F600060871F910F91FF90EF90DF90CF90BF90DF
:104F7000AF909F908F907F906F905F904F9008952B
:104F8000EFE6F0E080818D7F808308952F923F923D
:104F90004F925F926F927F928F929F92AF92BF9249
:104FA000CF92DF92EF92FF920F931F93DF93CF93F5
:104FB00000D000D000D0CDB7DEB7282F30E03E8340
:104FC0002D83F901EE0FFF1FE20FF31FEE0FFF1FFE
:104FD000EE0FFF1FE757FC4F8381882381F0E0919C
:104FE000C002F0E0B3E0EE0FFF1FBA95E1F7EA5D13
:104FF000FD4F80819181AC01461B570BBA01E091B6
:10500000C002F0E0A3E0EE0FFF1FAA95E1F7EA5D12
:10501000FD4F80819181CD80DE80CC0CDD1C1B0199
:10502000442455249C0140E050E029833A834B837B
:105030005C83969587956817790708F047C00D81BE
:105040001E810C0D1D1D000F111F000F111FF801F7
:10505000E357FC4FA080B180220C331C441C551C2C
:10506000C201B1010E947C2E3B014C0107571C4F2D
:10507000F801608571856A197B0980E090E00E94E3
:105080007C2E9B01AC01C401B3010E94F32F7B0174
:105090008C0169817A818B819C810E947C2E9B018D
:1050A000AC01C801B7010E94E32D7B018C01CC2427
:1050B000DD24C601B5010E947C2E9B01AC01C80114
:1050C000B7010E94162D0E94502E48C069817A8136
:1050D0008B819C810E947C2E4B015C012D813E8145
:1050E000C20ED31ECC0CDD1CCC0CDD1C49E853E0F9
:1050F000C40ED51EF60160847184C201B1010E9404
:105100007C2E7B018C01C501B40120E030E040E041
:105110005FEB0E94F32F9B01AC01C801B7010E9415
:10512000162D9B01AC010E94162D7B018C01F6010E
:10513000668177816619770980E090E00E947C2E75
:105140009B01AC01C801B7010E94F32FA501940196
:105150000E94E32D0E94502E660D771DED81FE8189
:10516000EE0FFF1F2D813E81E20FF31FEE0FFF1F99
:10517000EE0FFF1FE357FC4F0190F081E02D6E17FB
:105180007F0708F4BF01ED81FE81EE0FFF1F4D8107
:105190005E81E40FF51FEE0FFF1FEE0FFF1FE757B5
:1051A000FC4F868197818617970708F4BC017283AC
:1051B000618326960FB6F894DEBF0FBECDBFCF91A8
:1051C000DF911F910F91FF90EF90DF90CF90BF90F4
:1051D000AF909F908F907F906F905F904F903F9097
:1051E0002F900895482F50E0FA01EE0FFF1FE40FB3
:1051F000F51FEE0FFF1FEE0FFF1FE357FC4F01904F
:10520000F081E02DCB016E177F0708F4CF01FA0182
:10521000EE0FFF1FE40FF51FEE0FFF1FEE0FFF1F36
:10522000E757FC4F268137812817390708F4C90151
:105230009283818308951F920F920FB60F921124CB
:105240002F933F934F935F938F939F93EF93FF938E
:1052500030919102323090F42BB1832F90E0FC0119
:10526000EE0FFF1FE80FF91FEE0FFF1FEE0FFF1FDE
:10527000E757FC4F8081809582238BB9832F8F5F06
:10528000809391028230C9F0833010F01092910225
:105290002BB18091910290E0FC01EE0FFF1FE80F0F
:1052A000F91FEE0FFF1FEE0FFF1FE757FC4F808126
:1052B000282B2BB9418152810AC04091A303509100
:1052C000A4038091A1039091A203481B590B309134
:1052D000880020918900922F80E0830F911D840F18
:1052E000951F90938900809388008091A1039091ED
:1052F000A203840F951F9093A2038093A103209192
:10530000A3033091A4038217930720F01092A20305
:105310001092A103FF91EF919F918F915F914F9117
:105320003F912F910F900FBE0F901F9018959C01E9
:1053300040E050E084E0220F331F441F551F8A9540
:10534000D1F760E07DE281E391E00E94F2302150EC
:1053500030403093C5002093C40088E98093C10099
:1053600086E08093C2000895982F8091C00085FF49
:10537000FCCF9093C6000895FC0107C08091C00047
:1053800085FFFCCF9093C600319690819923B1F7A9
:1053900008951F920F920FB60F9211242F938F939F
:1053A0009F93EF93FF932091C600809192028823F0
:1053B00009F052C080913C04281771F480913502A5
:1053C000882351F01092350285EA93E090933402DD
:1053D0008093330210923D04809135028823E1F5D9
:1053E000E0913302F0913402208380913D048F5F7D
:1053F00080933D0480913B04882319F02D3001F502
:105400001AC080913D04823029F4213019F081E0E6
:105410008093350280913D04833021F4223010F0D6
:1054200086E001C085E08093320290913D04809136
:105430003202981729F481E080933502809392021A
:105440003196F0933402E093330280913D04863923
:1054500019F481E080933502FF91EF919F918F9134
:105460002F910F900FBE0F901F901895CF93DF9341
:10547000EC0130E044C04F5FE42FF0E0EB55FC4F0F
:1054800020812D534F5FE42FF0E0EB55FC4F7081EE
:105490004F5FE42FF0E04350EB55FC4F5081DE01AD
:1054A000A30FB11D922F92959F70E42FF0E0EB5562
:1054B000FC4F80818D53880F880F892B8C9361302E
:1054C00009F1972F9D533F5FFE01E30FF11D31500E
:1054D0002295207F892F86958695282B2083623000
:1054E00089F04C5F63503E5FFE01E30FF11D929522
:1054F000990F990F907C5D53952B90833F5F6623A6
:1055000009F0B9CFDF91CF910895982F8091920241
:10551000813009F04BC080913D04882309F446C0D6
:105520008091A703891709F041C040E050E020E0D6
:1055300006C0EB55FC4F8081480F511D2F5FE22FB5
:10554000F0E080913D0490E00397E817F9078CF3B1
:10555000CA019F70E0913D0426E0959587952A95B4
:10556000E1F7835CF0E0EE55FC4F20818217B1F447
:10557000E0913D044F735070942F935CF0E0ED5533
:10558000FC4F8081981751F460913D04665081EF83
:1055900092E043E00E94362A21E001C020E0F89426
:1055A0001092D4021092D302789401C020E080912E
:1055B000D3029091D4028C5E944048F48091A7036A
:1055C000813428F08B3518F481E08093B502109275
:1055D0009202822F089590E0823009F491E0909336
:1055E0003B04992311F083E201C080E880933C04DE
:1055F0000895AC0180913D04825080933D048091D8
:105600009202813091F420E009C0FA01E20FF11D0D
:10561000B0E0AB55BC4F8C9180832F5FA22FA60FBB
:1056200080913D04281788F302C010923D04109227
:10563000920280913D040895A0E3B0E0E2E2FBE233
:105640000C942F31A8E04E010894811C911CF401A8
:10565000BA2F1192BA95E9F729833A834B835C8379
:105660006D837E838F839887CE010996FC0111920A
:10567000AA95E9F7A986BA86CB86DC86ED86FE86F2
:105680000F87188B29813A814B815C812DA73EA71A
:105690004FA758AB79018A018FEF9FEFA0E0B0E0F0
:1056A000E822F9220A231B231A01442455242985C0
:1056B0003A854B855C8529A73AA74BA75CA759017A
:1056C0006A01A822B922CA22DB223A01882499243D
:1056D000C601B501A80197010E94B3306DA37EA356
:1056E0008FA398A7C401B3010E94B33069A37AA322
:1056F0008BA39CA3C601B501A20191010E94B33006
:105700007B018C01C401B3010E94B3305B016C01C9
:1057100089A19AA1ABA1BCA18E0D9F1DA01FB11F95
:1057200089A39AA3ABA3BCA32DA13EA14FA158A5C9
:10573000CA01AA27BB2729A13AA14BA15CA1280F26
:10574000391F4A1F5B1F29A33AA34BA35CA32E1545
:105750003F054007510740F480E090E0A1E0B0E051
:10576000A80EB91ECA1EDB1E89A19AA1ABA1BCA1BD
:105770009D01442755272A0D3B1D4C1D5D1D2D8F76
:105780003E8F4F8F58A36C01BB24AA248DA19EA1EC
:10579000AFA1B8A5A070B070A80EB91ECA1EDB1EBE
:1057A000A98EBA8ECB8EDC8E9A8C8B8C7C8C9E8D47
:1057B0006F8D78A1FE01719688E0DF011D928A95B8
:1057C000E9F72D8B9E8B6F8B788F2D853E854F85CE
:1057D00058896DA57EA58FA598A90E94B3307B013D
:1057E0008C012D813E814F81588569A57AA58BA5B5
:1057F0009CA50E94B330E60EF71E081F191F6D8985
:105800007E898F89988D6E0D7F1D801F911F6D8BF6
:105810007E8B8F8B988FEE892A2D392D482D572D11
:105820007E2F8F89988DE096E2E10C944B31EF92B8
:10583000FF920F93DF93CF93CDB7DEB760970FB68C
:10584000F894DEBF0FBECDBFA82F002309F461C0BE
:105850007E010894E11CF11C88E0F70111928A9501
:10586000E9F729833A834B835C836D837E83AF831F
:10587000988780E2801BE82FFF27E7FDF0954D8198
:105880005E816F817885181684F01D861E861F86BE
:10589000188A882799278E1B9F0B04C076956795D9
:1058A000579547958A95D2F728C0202F332727FD93
:1058B0003095DB01CA01022E04C0B695A7959795D5
:1058C00087950A94D2F78D879E87AF87B88B04C0DF
:1058D000440F551F661F771FEA95D2F789819A8179
:1058E000AB81BC8104C0B695A795979587952A95FD
:1058F000D2F7482B592B6A2B7B2B49875A876B870A
:105900007C8729853A854B855C856D857E85AF854D
:1059100098898A2F60960FB6F894DEBF0FBECDBF70
:10592000CF91DF910F91FF90EF900895EF92FF924A
:105930000F93DF93CF93CDB7DEB760970FB6F89490
:10594000DEBF0FBECDBFA82F002309F461C07E01CA
:105950000894E11CF11C88E0F70111928A95E9F79F
:1059600029833A834B835C836D837E83AF839887DF
:1059700080E2801BE82FFF27E7FDF09549815A81DF
:105980006B817C81181684F019861A861B861C860A
:10599000882799278E1B9F0B04C0440F551F661F35
:1059A000771F8A95D2F728C0202F332727FD3095FF
:1059B000DB01CA01022E04C0880F991FAA1FBB1F5A
:1059C0000A94D2F789879A87AB87BC8704C07695FB
:1059D000679557954795EA95D2F78D819E81AF815E
:1059E000B88504C0880F991FAA1FBB1F2A95D2F73C
:1059F000482B592B6A2B7B2B4D875E876F87788BC3
:105A000029853A854B855C856D857E85AF8598892E
:105A10008A2F60960FB6F894DEBF0FBECDBFCF9130
:105A2000DF910F91FF90EF9008955058BB27AA2760
:105A30000ED083C24CD230F051D220F031F49F3FCF
:105A400011F41EF41CC20EF4E095E7FB04C2E92F2A
:105A500096D280F3BA17620773078407950718F088
:105A600071F49EF5AEC20EF4E0950B2EBA2FA02D68
:105A70000B01B90190010C01CA01A0011124FF27FB
:105A8000591B99F0593F50F4503E68F11A16F040F6
:105A9000A22F232F342F4427585FF3CF46953795F5
:105AA0002795A795F0405395C9F77EF41F16BA0BBA
:105AB000620B730B840BBAF09150A1F0FF0FBB1F68
:105AC000661F771F881FC2F70EC0BA0F621F731FB1
:105AD000841F48F4879577956795B795F7959E3F0E
:105AE00008F0B3CF9395880F08F09927EE0F97959C
:105AF00087950895ECD158F080E891E009F49EEF85
:105B0000EDD128F040E851E059F45EEF09C0B7C18B
:105B100058C2E92FE07833D268F3092E052AC1F381
:105B2000261737074807590738F00E2E07F8E025E3
:105B300069F0E025E0640AC0EF6307F8009407FA13
:105B4000DB01B9019D01DC01CA01AD01EF934AD02F
:105B5000F4D10AD05F91552331F02BED3FE049E4B9
:105B600050FD49EC63CF0895DF93DD27B92FBF7750
:105B700040E85FE31616170648075B0710F4D92FB5
:105B80002BD29F938F937F936F93D2D2E0E7F0E075
:105B900079D1D3D12F913F914F915F9130D2DD23B5
:105BA00049F09058A2EA2AED3FE049EC5FE3D07853
:105BB0005D274DDFDF91C1C12AD108F481E008954E
:105BC00095D1E395CBC10CD0B8C188D140F07FD13D
:105BD00030F021F45F3F19F03EC15111F3C14FC1C4
:105BE000CED198F39923C9F35523B1F3951B550BE7
:105BF000BB27AA2762177307840738F09F5F5F4FA0
:105C0000220F331F441FAA1FA9F333D00E2E3AF0E0
:105C1000E0E830D091505040E695001CCAF729D0FA
:105C2000FE2F27D0660F771F881FBB1F2617370749
:105C30004807AB07B0E809F0BB0B802DBF01FF2779
:105C400093585F4F2AF09E3F510568F004C1BAC1D6
:105C50005F3FECF3983EDCF3869577956795B795B3
:105C6000F7959F5FC9F7880F911D9695879597F9CE
:105C70000895E1E0660F771F881FBB1F6217730747
:105C80008407BA0720F0621B730B840BBA0BEE1F5C
:105C900088F7E095089504D06894B11193C10895F0
:105CA00076D188F09F5790F0B92F9927B751A0F07F
:105CB000D1F0660F771F881F991F1AF0BA95C9F7A0
:105CC00012C0B13081F07DD1B1E008957AC1672F63
:105CD000782F8827B85F39F0B93FCCF38695779550
:105CE0006795B395D9F73EF4909580957095619539
:105CF0007F4F8F4F9F4F0895E89409C097FB3EF464
:105D000090958095709561957F4F8F4F9F4F992308
:105D1000A9F0F92F96E9BB279395F6958795779586
:105D20006795B795F111F8CFFAF4BB0F11F460FF46
:105D30001BC06F5F7F4F8F4F9F4F16C0882311F09E
:105D400096E911C0772321F09EE8872F762F05C0B2
:105D5000662371F096E8862F70E060E02AF09A954D
:105D6000660F771F881FDAF7880F9695879597F942
:105D70000895ADD018F011F0B1D038F480C022C130
:105D8000E92FFDD0B0F35523C9F3E7FB6217730782
:105D900084079507A8F199F3E92FFF2788232AF0B4
:105DA0003197660F771F881FDAF7952F5527442301
:105DB00032F091505040220F331F441FD2F7BB27BF
:105DC000E91BF50B621B730B840BB109C1F222F4C2
:105DD000620F731F841FB11D31972AF0660F771F62
:105DE000881FBB1FEFCF915050405AF041F08823DD
:105DF00032F0660F771F881F91505040C1F793957E
:105E000030C08695779567959F5FD9F7F8CF990F42
:105E10000008550FAA0BE0E8FEEF16161706E80774
:105E2000F907C0F012161306E407F50798F0621B95
:105E3000730B840B950B39F40A2661F0232B242B6A
:105E4000252B21F408950A2609F4A140A6958FEF89
:105E5000811D811D089597F99F6780E870E060E0DB
:105E600008959F3F31F0915020F48795779567957D
:105E7000B795880F911D9695879597F908959FEF8F
:105E800080EC0895DF93CF931F930F93FF92EF92CF
:105E9000DF927B018C01689405C0DA2EEF01AFD050
:105EA000FE01E894A5912591359145915591AEF368
:105EB000EF01CDDDFE019701A801DA9479F7DF90BB
:105EC000EF90FF900F911F91CF91DF9108950024E3
:105ED0000A941616170618060906089500240A944F
:105EE00012161306140605060895C9CF50D0E8F31C
:105EF000E894E0E0BB279F57F0F02AED3FE049EC43
:105F000006C0EE0FBB0F661F771F881F28F0B23A3E
:105F100062077307840728F0B25A620B730B840B75
:105F2000E3959A9572F7803830F49A95BB0F661F07
:105F3000771F881FD2F7904896CF092E0394000C44
:105F400011F4882352F0BB0F40F4BF2B11F460FF13
:105F500004C06F5F7F4F8F4F9F4F0895EF93E0FF17
:105F600006C0A2EA2AED3FE049EC5FEB70DDE5DF19
:105F70000F90039401FC9058EDE9F0E0E3C057FD69
:105F80009058440F551F59F05F3F71F04795880FA7
:105F900097FB991F61F09F3F79F08795089512163E
:105FA00013061406551FF2CF4695F1DF08C01616EA
:105FB00017061806991FF1CF86957105610508949B
:105FC0000895E894BB2766277727CB0197F90895B2
:105FD0001EDF08F48FEF08959B01AC0160E070E0D4
:105FE00080E89FE3F0CD0BD0A8CF71DF28F076DFFB
:105FF00018F0952309F02FCF42CF1124E3CFBFDF54
:10600000A0F3959FD1F3950F50E0551F629FF001CB
:10601000729FBB27F00DB11D639FAA27F00DB11D24
:10602000AA1F649F6627B00DA11D661F829F2227AD
:10603000B00DA11D621F739FB00DA11D621F839F34
:10604000A00D611D221F749F3327A00D611D231F0A
:10605000849F600D211D822F762F6A2F11249F5758
:1060600050408AF0E1F088234AF0EE0FFF1FBB1F7B
:10607000661F771F881F91505040A9F79E3F51051A
:1060800070F0E9CE9FCF5F3FECF3983EDCF386954E
:1060900077956795B795F795E7959F5FC1F7FE2BC5
:1060A000880F911D9695879597F9089511F40EF430
:1060B000E6CED7CE6CDFD0F39923D9F3CEF39F573A
:1060C000550B87FF38D00024A0E640EA90018058A5
:1060D0005695979528F4805C660F771F881F20F0EF
:1060E00026173707480730F4621B730B840B2029EF
:1060F00031294A2BA69517940794202531254A2744
:1061000058F7660F771F881F20F0261737074807B4
:1061100030F4620B730B840B200D311D411DA095D3
:1061200081F7B901842F9158880F96958795089526
:106130009B01AC0158CF91505040660F771F881FCC
:10614000D2F708959F938F937F936F93FF93EF936D
:106150009B01AC0148DFEF91FF9194DE2F913F91BD
:106160004F915F9140CF629FD001739FF001829F5A
:10617000E00DF11D649FE00DF11D929FF00D839FD6
:10618000F00D749FF00D659FF00D9927729FB00D73
:10619000E11DF91F639FB00DE11DF91FBD01CF0186
:1061A00011240895991B79E004C0991F961708F0EF
:1061B000961B881F7A95C9F780950895AA1BBB1B6B
:1061C00051E107C0AA1FBB1FA617B70710F0A61BF7
:1061D000B70B881F991F5A95A9F780959095BC0118
:1061E000CD010895A1E21A2EAA1BBB1BFD010DC013
:1061F000AA1FBB1FEE1FFF1FA217B307E407F50777
:1062000020F0A21BB30BE40BF50B661F771F881F52
:10621000991F1A9469F760957095809590959B01E8
:10622000AC01BD01CF01089597FB092E05260ED0C4
:1062300057FD04D0D7DF0AD0001C38F450954095A4
:10624000309521953F4F4F4F5F4F0895F6F790954A
:106250008095709561957F4F8F4F9F4F08952F9236
:106260003F924F925F926F927F928F929F92AF92E6
:10627000BF92CF92DF92EF92FF920F931F93CF9333
:10628000DF93CDB7DEB7CA1BDB0B0FB6F894DEBFCA
:106290000FBECDBF09942A88398848885F846E84F0
:1062A0007D848C849B84AA84B984C884DF80EE803A
:1062B000FD800C811B81AA81B981CE0FD11D0FB643
:1062C000F894DEBF0FBECDBFED010895FB01DC01E8
:1062D0008D91059080190110D9F3990B0895FB0158
:1062E000DC0105900D920020E1F70895FB01DC012F
:1062F0000D900020E9F7119701900D920020E1F731
:106300000895FB01DC018D91019080190110D9F3F2
:10631000990B0895FB01DC0101900D920020E1F73B
:106320000895FB019F01E8944230C4F04532B4F473
:106330004A3029F497FB1EF4909581959F4F642F66
:1063400077270E94DE30805D8A330CF0895D81936F
:10635000CB010097A1F716F45DE251931082C901B9
:106360000C942F32FA01CF93FF93EF93223044F134
:10637000253234F5C22FE894CA3049F497FB3EF435
:1063800090958095709561957F4F8F4F9F4F2C2FE3
:10639000332744275527FF93EF930E94F230EF9164
:1063A000FF91605D6A330CF0695D6193B901CA01C8
:1063B000605070408040904051F716F4CDE2C19398
:1063C00010828F919F91CF910C942F32DC01CB01E1
:1063D000FC01F999FECF06C0F2BDE1BDF89A3196F5
:1063E00000B40D9241505040B8F70895F999FECF8E
:1063F00092BD81BDF89A992780B50895A6E1B0E0D5
:1064000044E050E00C94E831A8E1B0E042E050E014
:106410000C94E831DC01CB0103C02D910E941532B0
:1064200041505040D0F70895262FF999FECF1FBA5A
:1064300092BD81BD20BD0FB6F894FA9AF99A0FBEAD
:1064400001960895242F0E941532252F0E9415329F
:106450000C942A320E941432272F0C941532DC013E
:10646000FC01672F71917723E1F7329704C07C918B
:106470006D9370836291AE17BF07C8F30895F894C7
:02648000FFCF4C
:106482003A20004D487A002A2000560A310A32008A
:10649200312E31300023636F3F5D3D3D45480D0095
:1064A2004469723A004469733A004265613A0041B4
:1064B2006C743A0050616E3A0054696C3A00614C57
:1064C2006F6E3A00614C61743A0061416C743A201B
:1064D20000684C6F6E3A00684C61743A0068416C17
:1064E200743A20003000C0120000201C00008025F9
:1064F200000040380000004B00000096000000E160
:106502000000000000001F55C003000001FECC0186
:106512004B0080008000002D002D007F00002D0028
:106522002D007F00280593020130000000000000CA
:106532006400000064006600980000009001000002
:1065420090019B016302042D2E2F31041415040CBB
:106552000D0421222324041D1E1F200102030435E1
:106562003604050607001B381227002C393A373546
:10657200373430003537363000353738300035386B
:106582003030003538323000353834300035383666
:106592003000EF01F401F901FE01030208020D02CD
:1065A200E803D3001A00FF0000014C036800FF0358
:0665B200400006A50301F4
:040000050080043C37
:00000001FF
/NGVideo5_8/tags/v1.10/Hexfiles
Property changes:
Added: bugtraq:number
+true
\ No newline at end of property
/NGVideo5_8/tags/v1.10/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.10/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.10/NGVideo_5_8GHz.pnps
0,0 → 1,0
<pd><ViewState><e p="NGVideo_5_8GHz" x="true"></e></ViewState></pd>
/NGVideo5_8/tags/v1.10/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.10/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.10/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.10/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.10/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.10/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.10/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.10/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.10/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
 
#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"};
uint8_t ch_stored; // Flag zur Speicherung, wenn Wert im Hauptdisplay geändert
uint8_t coldstart;
 
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
#define LEFT 1
#define MIDDLE 2
 
typedef struct
{
uint16_t min;
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.10/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.10/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.10/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)
{
PINB |= (1<<BEEPER);
PINB &= ~(1<<BEEPER);
_delay_ms(time);
PINB |= (1<<BEEPER);
PINB &= ~(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.10/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'
#define MARKER_SYNC 's'
 
#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
#define GPS_DISP_CALC 1
#define GPS_DISP_CURRENT 2
#define GPS_DISP_HOME 3
#define GPS_RX_COUNT 4
 
#define BAUDRATE 5
#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];
uint16_t* pudbm = udbm;
uint8_t wudbm;
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
 
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.10/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.10/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.10/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.10/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.10/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.10
Property changes:
Added: bugtraq:number
+true
\ No newline at end of property