Digitální seznam kontaktů, anglicky Digital Contact List - DCL
Digitální seznam kontaktů má jednu velikou výhodu. Změny firmware na jeho strukturu, umístění ani funkčnost nemají vliv. Prozatím (10.3.2025). Tím se stává výbornou oblastí pro studium a pokusy.
1) Popis formátu digitálního seznamu kontaktů
Radiostanice Anytone D878UV2+ může obsahovat až 500000 záznamů. Záznam je kompletní seznam údajů o jednom kontaktu. Jednotlivé údaje záznamu jsou uloženy v položkách. Seznam položek záznamu a jejich nejdůležitější vlastnosti najdete v následující tabulce.
Položka | Typ dat | Délka v paměti | Maximální délka v CPS |
---|---|---|---|
Call Type | číslo | 1 bajt | - |
ID | číslo | 4 bajty | 8 číslic |
Call Alert | číslo | 1 bajt | - |
Name | text UTF8 | proměnná | 16 znaků |
City | text UTF8 | proměnná | 15 znaků |
Callsign | text UTF8 | proměnná | 8 znaků |
State/Prov | text UTF8 | proměnná | 16 znaků |
Country | text UTF8 | proměnná | 16 znaků |
Remarks | text UTF8 | proměnná | 16 znaků |
Položka Call Type je ve skutečnosti pouze číslo. Význam jednotlivých hodnot je popsaný textově, ale výběr textového popisu nemůže změnit délku tohoto čísla, proto je údaj v posledním sloupečku tabulky proškrtnut. Přiřazení textů k používaným hodnotám je následující:
- 0 = Private Call
- 1 = Group Call
- 2 = All Call
Položka ID je číslo o maximální délce 8 číslic. V paměti radiostanice je uloženo tak, že každá číslice zabírá jednu polovinu bajtu (nibles). Například ID 4461234 bude uloženo jako $04, $46, $12, $34. Tyto čtyři bajty ale nelze z programátorského hlediska považovat za jedno číslo o velikosti DoubleWord. Jsou to samostatné bajty obsahující dvě samostatné hexadecimální číslice. Pokud bychom chtěli s ID provádět matematické operace, například ho vynásobit 2, nebude postup úplně jednoduchý. Bohužel právě tomuhle se v případě zápisu seznamu kontaktů do vysílačky nevyhneme.
Položka Call Alert je ve skutečnosti také jen číslo, tak jako položka Call Type. Význam jednotlivých hodnot je následující:
- 0 = None
- 1 = Ring
- 2 = Online Alert
Zbývající položky jsou texty. Navzdory tomu, že v originálním programu CPS mají omezení maximální délky, ve skutečnosti mohou mít v paměti vysílačky délku libovolnou. Jedná se o takzvané textové řetězce ukončené nulou. Tento formát se používá kvůli šetření místa v paměti. Místo pevně vyhrazeného prostoru pro každou položku se zabere vždy jen místo podle délky aktuálně ukládaného textu. Přesto není možné používat jakoukoliv délku textů, protože firmware umí zobrazit na displeji vysílačky jen text do délky stanovené v originálním CPS. Při použití delších textů se obvykle na displeji nezobrazí nic.
Za zmínku stojí ještě dvě věci. Délka textu položky City je o jeden znak kratší, než délka většiny ostatních textů. Další zajímavostí je délka textu Callsign, která může být až 8 znaků. Ve skutečnosti ale uživatelé všechny volací znaky omezují pouze na maximálně 6 písmen. Tyto anomálie se zřejmě snaží o udržení kompatibility s nějakým starším formátem dat, který se dodnes používá ve vysílačkách jiných výrobců.
2) Čtení digitálního seznamu kontaktů z vysílačky
Ke čtení digitálního seznamu kontaktů lze použít protokol popsaný v předchozím článku. Potřebujeme jen vědět, z jakých adres máme číst. Tou hlavní adresou je $05500000, kde seznam začíná. Kde ale končí? Jak jsme si popsali výše, textové položky mohou mít různou délku a proto bude mít různou délku i celý seznam. Takže druhou nejdůležitější adresou je $04840000. Od této adresy je ve 4 bajtech uložen počet záznamů seznamu a za ním je v dalších 4 bajtech adresa první volné paměti za seznamem kontaktů. Tyto údaje lze vyčíst jediným příkazem. Nejprve spustíme komunikaci s vysílačkou. Pak zadáme následující příkaz pro čtení:
52 04840000 10
Příkaz přečte 16 bajtů od adresy $04840000. Moje vysílačka aktuálně odpovídá takto:
57 04840000 10 44080000 E9135405 0000000000000000 39 06
Série čtyř bajtů 44080000 představuje počet záznamů v seznamu. Ale pozor, bajty jsou uloženy od nejníže umístěných číslic, tak zvaný formát LSB. To znamená, že skutečný počet je v opačném pořadí bajtů, tedy $00000844 = desítkově 2116 záznamů. Stejným způsobem je uložena i adresa konce seznamu. Takže posloupnost bajtů E9135405 je ve skutečnosti adresa $055413E9. Tím jsme zjistili, že v mé vysílačce je v seznamu kontaktů 2116 záznamů a jsou umístěny v paměti v rozmezí adres $05500000 až $055413E9.
Teď už můžeme začít číst data z paměti vysílačky.
< 52 05500000 10
> 57 05500000 10 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xx 06
< 52 05500010 10
> 57 05500010 10 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xx 06
< 52 05500020 10
> 57 05500020 10 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xx 06
a tak dále až po poslední načtená data od adresy $055413E0. Pak už můžeme ukončit komunikaci s vysílačkou příkazem "END". Tím máme k dispozici kopii digitálního seznamu kontaktů. Jedná se samozřejmě jen o surová data. Dalším krokem musí být rozdělení těchto dat na jednotlivé záznamy a jednotlivé položky a jejich zápis do vhodné databáze. Správný postup závisí na tom, jaký programovací jazyk použijete. Ale to už je mimo téma tohoto článku.
Zdá se vám to snadné? To je dobře. Protože teď to trochu zkomplikujeme. Všechno to, co jsme si dosud řekli o čtení seznamu kontaktů z vysílačky, platí jen pro relativně malý počet záznamů. Přesně řečeno pro seznam, který je kratší, než 100000 bajtů. Seznam je totiž v paměti vysílačky rozdělen do bloků právě po 100000 = $186A0 bajtech, které na sebe nenavazují. Mezi dvěma sousedními bloky je rozestup vždy $40000 bajtů. Takže pro delší seznam platí, že po adrese $0551869F je další část uložena od adresy $05540000. Stejně tak po adrese $0555869F se pokračuje na adrese $05580000. A tak pořád dál. Takže při čtení seznamu kontaktů musíme navíc ještě respektovat členění do bloků, velikost bloků a jejich rozestup. Pořád se vám to zdá snadné? To je moc dobře. Protože zápis seznamu kontaktů do vysílačky je ještě o něco složitější.
2) Zápis digitálního seznamu kontaktů do vysílačky
Čtení dat z vysílačky je poměrně bezpečné. I když zvolíte nesprávný postup, nebude to mít vliv na funkčnost vysílačky. Pouze přečtete nesprávná data. Se zápisem je to už horší. Pokud omylem začnete zapisovat na nesprávné adresy, může se stát, že vysílačka přestane reagovat na svoje ovládací tlačítka. Tedy přestane vysílat. V tom případě do ní musíte znovu originálním programem CPS nahrát její konfiguraci ze souboru rdt. Proto je dobré mít před zahájením experimentů zálohu aktuálního nastavení vysílačky. Pro uklidnění situace mohu říct, že i když se mi to několikrát stalo, nikdy nebylo potřeba spouštět tovární reset nebo znovu nahrávat celý firmvare. Přehrání konfigurace ze souboru rdt vždy zabralo.
Zápis seznamu kontaktů do vysílačky je složitější, protože se ještě navíc musí zapisovat doprovodná data od adresy $04000000. Pro každý záznam se musí zapsat 4 bajtové číslo, které je dvojnásobkem ID. Za něj se zapíše 4 bajtová adresa, na které tento záznam začíná. Celý proces zápisu seznamu kontaktů do vysílačky si ukážeme na příkladu. Předpokládejme, že máme seznam obsahující tři záznamy podle následující tabulky.
Záznam číslo | obsahuje ID | dvojnásobek ID | délka záznamu | počáteční adresa |
1. | 4460987 | 088C130E | 100 = $64 | $00000000 |
2. | 3012345 | 0602468A | 150 = $96 | $00000064 |
3. | 4460123 | 088C0246 | 75 = $4B | $000000FA |
Celý seznam bude dlouhý $64 + $C8 + $4B = $145 bajtů. Zabere tedy prostor v paměti po adresu $05500000 + $145 = $05500145. Tím máme údaje pro zápis od adresy $04840000. To bude první krok.
< 57 04840000 10 03000000 45015005 0000000000000000 xx 06
> 06
- $57: příznak zápisu do paměti vysílačky
- $04840000: adresa paměti, od které se bude zapisovat
- $10: počet zapisovaných bajtů, desítkově 16
- 03000000: počet záznamů ve formátu LSB, tedy číslo 00000003, zkráceně 3
- 45015005: první volná adresa za seznamem ve formátu LSB, tedy $05500145
- xx: kontrolní součet CRC
- 06: příznak konce příkazu
Vysílačka potvrdí přijetí dat číslem $06. V dalším kroku musíme vytvořit doprovodná data zapisovaná od adresy $04000000. Tedy pro každý záznam vypočítat dvojnásobek ID a adresu jeho začátku. Předpokládejme, že v prvním záznamu máme hodnotu ID = 4460987 uloženou v proměnné jako běžné celé číslo. Jeho hexadecimální hodnota je $4411BB a to je špatně. Proto nemůžeme tohle číslo přímo vynásobit dvěma, ale musíme podstoupit následující proceduru.
- číslo 4460987 převedeme na text, dostaneme "4460987"
- protože ID musí mít 8 číslic, doplníme úvodní 0, dostaneme "04460987"
- protože jednotlivé číslice mají být hexadecimální, přidáme na začátek textového řetězce znak $, dostaneme "$04460987"
- Tento textový zápis hexadecimálního čísla převedeme zpět na číslo, v Delphi funkcí StrToInt($04460987), dostaneme číslo 71698823
- Toto číslo vynásobíme 2, dostaneme 71698823 * 2 = 143397646
- Toto číslo převedeme na textový řetezec hexadecimálních znaků, v delphi funkcí IntToHex(143397646, 8), dostaneme"088C130E"
- Tento text rozdělíme na čtyři samostatné texty po dvou znacích, dostaneme "08", "8C", "13", "23"
- Protože se jedná o hexadecimální znaky, doplníme na začátky znak $, dostaneme "$08", "$8C", "$13", "$23"
- Převodem těchto textů na čísla, v Delphi funkcí StrToInt($08), ... dostaneme cílové bajty pro zápis do vysílačky, tedy $08, $8C, $13, $23
Stejným způsobem přepočítáme ID druhého a třetího záznamu. Počáteční adresa prvního záznamu je vždy nula, počáteční adresu druhého záznamu získáme připočtením délky prvního záznamu, tedy 0 + $64 = $00000064. Počáteční adresa třetího záznamu je 0 + $64 + $96 = $000000FA. Tím známe všechy potřebné údaje a můžeme je zapsat od adresy $04000000.
< 57 04000000 16 23138C08 00000000 8A460206 64000000 xx 06
> 06
< 57 04000010 16 46028C08 FA000000 FFFFFFFF FFFFFFFF xx 06
> 06
Při každém zápisu se posílají do vysílačky údaje dvou záznamů. Nejprve dvojnásobek ID prvního záznamu ve formátu LSB, za ním adresa tohoto záznamu ve formátu LSB. Pak dvojnásobek ID následujícího záznamu a za ním jeho adresa, obojí ve formátu LSB. Druhým zápisem se posílají údaje o třetím záznamu. Protože další záznam už není, doplní se volné pozice v datech hodnotami $FF. Pokud máme větší počet záznamů, postupujeme u všech dvojic stejným způsobem. Doplnění dat hodnotami FF se provádí až na konci v případě lichého počtu záznamů. Vypadá to složitě, ale po chvíli přemýšlení si lze na neustále se opakující postup zvyknout. Bohužel i tady platí, že v případě dlouhých dat dojde k rozdělení na bloky. Tyto bloky mají délku $1F400. Rozestup bloků je $40000.
Na závěr ve třetím kroku začneme zapisovat vlastní data od adresy $05500000. U delších seznamů nesmíme zapomenout na členění do bloků. Pokud u posledního zápisu nevyplní užitečná data celý 16 bajtový prostor, doplní se nulami. Za tímto posledním zápisem se přidají ještě tři 16 bajtové pakety vyplněné samými nulami. Tedy například:
< 57 055C8040 16 00000000000000000000000000000000 xx 06
> 06
< 57 055C8050 16 00000000000000000000000000000000 xx 06
> 06
< 57 055C8060 16 00000000000000000000000000000000 xx 06
> 06
Všechny tyto nuly navíc nejsou platná data seznamu kontaktů a proto se nezapočítávají do adresy konce seznamu, kterou jsme v prvním kroku zapsali na adresu $04840000. A to už je opravdu všechno. Jako domácí cvičení si zkuste rozebrat ukázku komunikace na konci předchozího článku. Jaké ID je v použitém záznamu?