Knjižnica z21 drive

Na temo elektronike in digitalne tehnike na področju železniške makete.
Uporabniški avatar
grizeldi
Strojevodja I
Strojevodja I
Prispevkov: 294
Pridružen: 30.01.2013, 13:20
Kraj: Ljubljana

Knjižnica z21 drive

OdgovorNapisal/-a grizeldi » 21.08.2015, 13:06

Med počitnicami sem se lotil izdelave java knjižnice za komunikacijo z DCC centralo z21 (več http://www.vlaki.info/forum/viewtopic.php?f=36&t=8338). Spisal sem vso kodo, ki naj bi bila končana in pripravljena za uporabo. Žal pa stvar ne deluje tako kot bi morala in zato bi rabil malo pomoči, predvsem programerskega dela "ajznponarjoljubcev" :P .
Težava je, da ko naj bi program preverjal status lokomotive vsake 3 sekunde, se nič ne spremeni, čeprav jaz medtem vozim lokomotive gor in dol z mobilno aplikacijo. Sumim da je kriv čuden način določanja "Loco addressa".

Rocova dokumentacija pravi (prevedeno v angleščino z google translate, ker ne znam nemško):
The following applies: Lok-address = (Adr_MSB & 0x3F) << 8 + Adr_LSB

Se pravi da je iz tega treba izračunati Adr_MSB in Adr_LSB. Jaz ne znam dovolj matematike (ravnokar končal OŠ), da bi to enačbo obrnil, zato sem se s tem vprašanjem obrnil na stack overflow. Tam sem dobil odgovor, ki v teoriji deluje do 63 in sem ga nekajkrat tudi stestiral, a v kombinaciji z z21 ne deluje.

Rocu sem že poslal mail v katerem jih prosim za izvorno kodo android mobilne aplikacije, a sumim da ne bom dobil nič. Še ena ideja je da bi uporabil "network sniffer" a se mi ne sanja kako se to vzpostavi.

Če ima kdo kakšne napotke zame, se priporočam.

Pa še mal linkov:
z21 dokumentacija za programerje
github repozitorij projekta
LJ363
Strojevodja I
Strojevodja I
Prispevkov: 1525
Pridružen: 30.07.2007, 17:27

Re: Knjižnica z21 drive

OdgovorNapisal/-a LJ363 » 21.08.2015, 15:06

Formula, ki si jo napisal na stack overflow, je čisto nekaj drugega kot ta zgoraj.
Kaj pomeni MSB in LSB veš? Verjetno tudi, da so v Javi vsi numerični tipi signed, tudi byte?
Če imaš v Adr_MSB in Adr_LSB (predvidevam da imaš byte spremenljivki) pravilne vrednosti, jih sestavi na naslednji način (tisti | znak vmes je OR):
Lok-address = ((Adr_MSB & 0x3F) << 8 ) | (Adr_LSB & 0xFF)

V drugo smer gre nekako takole (Lok-address je verjetno tipa int)
Adr_LSB = (Lok-address & 0xFF)
Adr_MSB = ((Lok-address >>> 8 ) & 0x3F)
Uporabniški avatar
grizeldi
Strojevodja I
Strojevodja I
Prispevkov: 294
Pridružen: 30.01.2013, 13:20
Kraj: Ljubljana

Re: Knjižnica z21 drive

OdgovorNapisal/-a grizeldi » 21.08.2015, 15:37

LJ363 napisal/-a:Formula, ki si jo napisal na stack overflow, je čisto nekaj drugega kot ta zgoraj.
Kaj pomeni MSB in LSB veš? Verjetno tudi, da so v Javi vsi numerični tipi signed, tudi byte?
Če imaš v Adr_MSB in Adr_LSB (predvidevam da imaš byte spremenljivki) pravilne vrednosti, jih sestavi na naslednji način (tisti | znak vmes je OR):
Lok-address = ((Adr_MSB & 0x3F) << 8 ) | (Adr_LSB & 0xFF)

V drugo smer gre nekako takole (Lok-address je verjetno tipa int)
Adr_LSB = (Lok-address & 0xFF)
Adr_MSB = ((Lok-address >>> 8 ) & 0x3F)

Formula je po testiranjih na stack overflowu enaka kot ta ki sem jo napisal (dodatni oklepaj je tam samo zaradi boljše razumljivosti). Da je javin byte signed vem, ker mi je to med programiranjem povzročilo precej preglavic. Žal pa ne vem kaj naj bi pomenilo MSB in LSB :( . In ja, zanima me predvsem obratna smer. Bom stestiral in povem rezultate.
LJ363
Strojevodja I
Strojevodja I
Prispevkov: 1525
Pridružen: 30.07.2007, 17:27

Re: Knjižnica z21 drive

OdgovorNapisal/-a LJ363 » 21.08.2015, 16:10

Dodatna oklepaja povsem spremenita potek izvajanja operacij in rezultat je čisto drugačen. Na primer (1 + 1) * 1 + 1 ni enako kot (1 + 1) * (1 + 1).
MSB in LSB sta v tem primeru Most Significant Byte in Least Significant Byte. 16-bitno število imaš sestavljeno iz dveh bytov (2*8-bitov), nekaj na to temo pa si lahko pogledaš recimo tu: http://www.mobilefish.com/tutorials/java/java_quickguide_short.html
Uporabniški avatar
grizeldi
Strojevodja I
Strojevodja I
Prispevkov: 294
Pridružen: 30.01.2013, 13:20
Kraj: Ljubljana

Re: Knjižnica z21 drive

OdgovorNapisal/-a grizeldi » 21.08.2015, 16:51

LJ363 napisal/-a:V drugo smer gre nekako takole (Lok-address je verjetno tipa int)
Adr_LSB = (Lok-address & 0xFF)
Adr_MSB = ((Lok-address >>> 8 ) & 0x3F)

Tole sem sprobal in lahko zagotovim da ne dela. Pošljem "request" za podatke o lokomotivi #5, program pa to interpretira kot #1280.
Hmm?

LJ363 napisal/-a:Dodatna oklepaja povsem spremenita potek izvajanja operacij in rezultat je čisto drugačen. Na primer (1 + 1) * 1 + 1 ni enako kot (1 + 1) * (1 + 1).
MSB in LSB sta v tem primeru Most Significant Byte in Least Significant Byte. 16-bitno število imaš sestavljeno iz dveh bytov (2*8-bitov), nekaj na to temo pa si lahko pogledaš recimo tu: http://www.mobilefish.com/tutorials/java/java_quickguide_short.html

Zadevo sem testiral z ali brez oklepajev pa je bil rezultat isti. Ali prav razumem, da lahko uporabim javin tip short, ki ga nato razstavim na dva bajta?
LJ363
Strojevodja I
Strojevodja I
Prispevkov: 1525
Pridružen: 30.07.2007, 17:27

Re: Knjižnica z21 drive

OdgovorNapisal/-a LJ363 » 21.08.2015, 17:40

grizeldi napisal/-a:
LJ363 napisal/-a:V drugo smer gre nekako takole (Lok-address je verjetno tipa int)
Adr_LSB = (Lok-address & 0xFF)
Adr_MSB = ((Lok-address >>> 8 ) & 0x3F)

Tole sem sprobal in lahko zagotovim da ne dela. Pošljem "request" za podatke o lokomotivi #5, program pa to interpretira kot #1280.
Hmm?

Link, ki sem ti ga poslal nisi prebral?
Pri komunikacijah se običajno pošilja po byte, zato moraš pri več-bytnih tipih upoštevat endian. Se pravi moraš vedet v kakšnem vrstnem redu jih pošlješ.
1280 je 0x0500, se pravi pošiljaš byta v napačnem vrstnem redu.
Uporabniški avatar
grizeldi
Strojevodja I
Strojevodja I
Prispevkov: 294
Pridružen: 30.01.2013, 13:20
Kraj: Ljubljana

Re: Knjižnica z21 drive

OdgovorNapisal/-a grizeldi » 21.08.2015, 17:46

Link sem prebral, in bajta pošiljam v vrstnem redu, kot piše v dokumentaciji. Za vsak primer sem zadevo obrnil in dobim loc address #0... :cry:
LJ363
Strojevodja I
Strojevodja I
Prispevkov: 1525
Pridružen: 30.07.2007, 17:27

Re: Knjižnica z21 drive

OdgovorNapisal/-a LJ363 » 21.08.2015, 17:49

Če imaš 0x05 in 0x00 jih lahko združiš kot 0x0500 kar je 1280 ali pa 0x0005 kar je 5. Kako pa ti je uspelo dobit 0 pa ne vem?
LJ363
Strojevodja I
Strojevodja I
Prispevkov: 1525
Pridružen: 30.07.2007, 17:27

Re: Knjižnica z21 drive

OdgovorNapisal/-a LJ363 » 21.08.2015, 18:03

Treba je tudi upoštevat prioritete operatorjev v Javi in ustrezno postavit oklepaje, glede na to kaj bi rad izračunal: http://introcs.cs.princeton.edu/java/11precedence/
Če bi namesto + uporabil raje |, bi bil rezultat precej drugačen.
Uporabniški avatar
grizeldi
Strojevodja I
Strojevodja I
Prispevkov: 294
Pridružen: 30.01.2013, 13:20
Kraj: Ljubljana

Re: Knjižnica z21 drive

OdgovorNapisal/-a grizeldi » 21.08.2015, 18:05

Razumem kaj mi poskuas dopovedat. Bom moral se malo testirat. Kako pa sem dobil 0 pa tudi meni ni jasno.
Za danes pa sem s programiranjem koncal in predvidoma nadaljujem v ponedljek. Hvala za vso pomoc.
LJ363
Strojevodja I
Strojevodja I
Prispevkov: 1525
Pridružen: 30.07.2007, 17:27

Re: Knjižnica z21 drive

OdgovorNapisal/-a LJ363 » 21.08.2015, 18:10

Na hitro sem poiskal "endian" v Z21 dokumentaciji in ponekod je uporabljen big drugje pa little endian, se pravi boš moral precej pazit v kakšnem vrstnem redu se pošilja byte.
Uporabniški avatar
mkx
Strojevodja I
Strojevodja I
Prispevkov: 3442
Pridružen: 20.03.2011, 9:03
Kraj: Dolenjska

Re: Knjižnica z21 drive

OdgovorNapisal/-a mkx » 21.08.2015, 21:18

@grizeldijev opis formule za lokomotivski naslov izgleda zelo v liniji s tem, kako se uporablja dolge DCC naslove. Dolgi DCC naslovi so med 0 in okoli 10000. V resnici DCC naslavljanje nudi 14 bitov, vendar za dolge naslove ni na voljo ves nabor (14 bitov bi pomenilo 16384), ampak le 10239. Nekateri proizvajalci so to zaradi enostavnejšega uporabniškega vmesnika potem zmanjšali na 0-9999 (4-mestne decimalne številke).

  • V CV17 se vpiše 192 + MSB (prištevanje 192 je efektivno postavljanje zgornjih dveh bitov). Iz @grizeldijevega citata Rocove dokumentacije sledi, da je tam omenjeni Adr_MSB očitno vrednost CV17, maskiranje z 0x3F pobriše zgornja dva bita.
  • V CV18 se vpiše LSB. Namesto maskiranja (addr & 0xFF) se lahko naredi celištevilčno aritmetiko: LSB=addr-(addr/256)*256.

Namesto maskiranja z 0x3F, ki se ga opravlja na MSB za zagotovitev, da je rezultat 6-bitna vrednost, se lahko naredi tudi celoštevilčno aritmetiko: MSB-(MSB/64)*64. Ker predpostavimo, da je v Adr_MSB res vrednost iz CV17, ki mora po definiciji imeti leva (prva) dva bita postavljena, lahko tole poenostavimo v MSB-192.

Če je torej znan naslov lokomotive (npr. 1234), se poračuna Adr_MSB in Adr_LSB takole:

Adr_MSB = 192 + (address/256) (za primer: Adr_MSB = 192+4 = 196 = Adr_MSB)

Adr_LSB = address - (address/256)*256 (za primer: Adr_LSB =1234-(1234/256)*256 = 1234-4*256 =1234-1024 = 210 = Adr_LSB )

Iz Adr_MSB in Adr_LSB pa se poračuna naslov takole:

address = (Adr_MSB-192)*256 + Adr_LSB

za primer: address = (196-192)*256+210 = 4*256+210 = 1024+210 = 1234 = address

Seveda se lahko vse zgornje namesto z celoštevilskimi operacijami naredi z bitnimi operacijami:

Adr_MSB = (address >> 8 )|0xC0

Adr_LSB = address & 0xFF

in

address = ((Adr_MSB & 0x3F) << 8 ) | Adr_LSB

Seveda so oklepaji še kako pomembni, saj ni nepomembno v kakšnem vrstnem redu so operacije opravljene.

V vsakem primeru (celoštevilčna aritmetika ali bitne operacije) pa je treba poskrbeti, da je address 16-bitna spremenljivka/vrednost, Adr_MSB in Adr_LSB pa 8-bitni. V nasprotnem primeru se lahko zgodi, da se kje valjajo kakšni postavljeni biti ki vse skupaj odnesejo v nedefinirani smeri.


Čez nekaj časa ... sem šel pogledat dokumentacijo s povezave. Takoj za tekstom, ki ga je @grizeldi dal v google translate, piše še tole:
Bei Lok-Adressen ≥ 128 müssen die beiden höchsten Bits in DB1 auf 1 gesetzt sein:
DB1 = (0xC0 | Adr_MSB). Bei Lokadressen < 128 sind diese beiden höchsten bits ohne Bedeutung.

Kar pomeni naslednje: če je lok naslov 128 ali večji, morata biti zgornja bita v DB1 (Adr_MSB) postavljena na 1, kar se doseže (druga vrstica) z logičnim OR z vrednostjo 0xC0 (ki je v binarnem prikazu 11000000, v decimalnem pa 192). Kar je identično prištevanju 192 kot je to v mojem primeru. Ta citat v bistvu dokazuje, da sta DB1 in DB2 res kar CV17 in CV18.

Pa še mimogrede: DCC standard določa, da se lahko uporabljajo kratki in dolgi naslovi. Kratki naslovi so tam nekje do 99 ali 127 (odvisno od implementacije) in se shranjujejo v CV01. Dolgi naslovi so lahko teoretično prav tako od 1 naprej in se vpisujejo v CV17 in CV18. Ko DCC centrala (recimo z21) naslavlja lokomotive, najprej pošlje en byte naslova. Če je levi bit (MSB) naslova 0, dekoder ve, da gre za kratki naslov (zato omejitev do 127). Če levi bit ni 0, dekoder pogleda dva leva bita in če sta 11 (decimalno je to 3), dekoder ve da gre za dolgi naslov, sestavljen iz dveh bytov. Zato se mora pri MSB (=CV17) vedno postaviti dva leva bita (= prišteti 192) in od tu je omejitev na 14-bitno dolžino naslova.
Več o tem je v https://sites.google.com/site/markgurries/home/technical-discussions/decoder-addressing/decoding-addresses.
Rocova implementacija v z21 očitno predpostavi, da gre pri naslovih do 127 za kratke naslove ("Bei Lokadressen < 128 sind diese beiden höchsten bits ohne Bedeutung", torej brez pomena ... v dekoderjih so kratki naslovi zapisani v CV01). Dalo bi se ugotoviti, ali se lahko kljub temu uporablja dolgo naslavljanje z naslovom, nižjim od 128 (CV17=192, CV18<128), mislim pa, da ne.
LP, Metod
Uporabniški avatar
grizeldi
Strojevodja I
Strojevodja I
Prispevkov: 294
Pridružen: 30.01.2013, 13:20
Kraj: Ljubljana

Re: Knjižnica z21 drive

OdgovorNapisal/-a grizeldi » 24.08.2015, 16:57

mkx napisal/-a:@grizeldijev opis formule za lokomotivski naslov izgleda zelo v liniji s tem, kako se uporablja dolge DCC naslove. Dolgi DCC naslovi so med 0 in okoli 10000. V resnici DCC naslavljanje nudi 14 bitov, vendar za dolge naslove ni na voljo ves nabor (14 bitov bi pomenilo 16384), ampak le 10239. Nekateri proizvajalci so to zaradi enostavnejšega uporabniškega vmesnika potem zmanjšali na 0-9999 (4-mestne decimalne številke).

  • V CV17 se vpiše 192 + MSB (prištevanje 192 je efektivno postavljanje zgornjih dveh bitov). Iz @grizeldijevega citata Rocove dokumentacije sledi, da je tam omenjeni Adr_MSB očitno vrednost CV17, maskiranje z 0x3F pobriše zgornja dva bita.
  • V CV18 se vpiše LSB. Namesto maskiranja (addr & 0xFF) se lahko naredi celištevilčno aritmetiko: LSB=addr-(addr/256)*256.

Namesto maskiranja z 0x3F, ki se ga opravlja na MSB za zagotovitev, da je rezultat 6-bitna vrednost, se lahko naredi tudi celoštevilčno aritmetiko: MSB-(MSB/64)*64. Ker predpostavimo, da je v Adr_MSB res vrednost iz CV17, ki mora po definiciji imeti leva (prva) dva bita postavljena, lahko tole poenostavimo v MSB-192.

Če je torej znan naslov lokomotive (npr. 1234), se poračuna Adr_MSB in Adr_LSB takole:

Adr_MSB = 192 + (address/256) (za primer: Adr_MSB = 192+4 = 196 = Adr_MSB)

Adr_LSB = address - (address/256)*256 (za primer: Adr_LSB =1234-(1234/256)*256 = 1234-4*256 =1234-1024 = 210 = Adr_LSB )

Iz Adr_MSB in Adr_LSB pa se poračuna naslov takole:

address = (Adr_MSB-192)*256 + Adr_LSB

za primer: address = (196-192)*256+210 = 4*256+210 = 1024+210 = 1234 = address

Seveda se lahko vse zgornje namesto z celoštevilskimi operacijami naredi z bitnimi operacijami:

Adr_MSB = (address >> 8 )|0xC0

Adr_LSB = address & 0xFF

in

address = ((Adr_MSB & 0x3F) << 8 ) | Adr_LSB

Seveda so oklepaji še kako pomembni, saj ni nepomembno v kakšnem vrstnem redu so operacije opravljene.

V vsakem primeru (celoštevilčna aritmetika ali bitne operacije) pa je treba poskrbeti, da je address 16-bitna spremenljivka/vrednost, Adr_MSB in Adr_LSB pa 8-bitni. V nasprotnem primeru se lahko zgodi, da se kje valjajo kakšni postavljeni biti ki vse skupaj odnesejo v nedefinirani smeri.


Čez nekaj časa ... sem šel pogledat dokumentacijo s povezave. Takoj za tekstom, ki ga je @grizeldi dal v google translate, piše še tole:
Bei Lok-Adressen ≥ 128 müssen die beiden höchsten Bits in DB1 auf 1 gesetzt sein:
DB1 = (0xC0 | Adr_MSB). Bei Lokadressen < 128 sind diese beiden höchsten bits ohne Bedeutung.

Kar pomeni naslednje: če je lok naslov 128 ali večji, morata biti zgornja bita v DB1 (Adr_MSB) postavljena na 1, kar se doseže (druga vrstica) z logičnim OR z vrednostjo 0xC0 (ki je v binarnem prikazu 11000000, v decimalnem pa 192). Kar je identično prištevanju 192 kot je to v mojem primeru. Ta citat v bistvu dokazuje, da sta DB1 in DB2 res kar CV17 in CV18.

Pa še mimogrede: DCC standard določa, da se lahko uporabljajo kratki in dolgi naslovi. Kratki naslovi so tam nekje do 99 ali 127 (odvisno od implementacije) in se shranjujejo v CV01. Dolgi naslovi so lahko teoretično prav tako od 1 naprej in se vpisujejo v CV17 in CV18. Ko DCC centrala (recimo z21) naslavlja lokomotive, najprej pošlje en byte naslova. Če je levi bit (MSB) naslova 0, dekoder ve, da gre za kratki naslov (zato omejitev do 127). Če levi bit ni 0, dekoder pogleda dva leva bita in če sta 11 (decimalno je to 3), dekoder ve da gre za dolgi naslov, sestavljen iz dveh bytov. Zato se mora pri MSB (=CV17) vedno postaviti dva leva bita (= prišteti 192) in od tu je omejitev na 14-bitno dolžino naslova.
Več o tem je v https://sites.google.com/site/markgurries/home/technical-discussions/decoder-addressing/decoding-addresses.
Rocova implementacija v z21 očitno predpostavi, da gre pri naslovih do 127 za kratke naslove ("Bei Lokadressen < 128 sind diese beiden höchsten bits ohne Bedeutung", torej brez pomena ... v dekoderjih so kratki naslovi zapisani v CV01). Dalo bi se ugotoviti, ali se lahko kljub temu uporablja dolgo naslavljanje z naslovom, nižjim od 128 (CV17=192, CV18<128), mislim pa, da ne.


Wow @mkx hvala za "predavanje". S pomočjo tega mi je uspelo vpisat pravilne številke da mi zdaj z21 pošilja podatke. Zdaj morm le še napisat algoritem ki bo to naredil namesto mene, ampak že vem kako bom to naredil, tako da je še samo stvar časa kdaj bo zadeva vsaj približno uporabna.
Uporabniški avatar
grizeldi
Strojevodja I
Strojevodja I
Prispevkov: 294
Pridružen: 30.01.2013, 13:20
Kraj: Ljubljana

Re: Knjižnica z21 drive

OdgovorNapisal/-a grizeldi » 24.08.2015, 17:20

Ok @mkx in @LJ363 hvala obema, prejemanje podatkov deluje. Zdaj moram popravit interpretacijo podatkov, potem pa sledi pošiljanje komand za vožnjo in spreminjanje vrednosti funkcij (F0, F1, F2...).
Uporabniški avatar
grizeldi
Strojevodja I
Strojevodja I
Prispevkov: 294
Pridružen: 30.01.2013, 13:20
Kraj: Ljubljana

Re: Knjižnica z21 drive

OdgovorNapisal/-a grizeldi » 26.08.2015, 17:42

Moram se pohvalit da je knjižnica že skoraj končana :)
Uspešno dobivam podatke o lokomotivah in spreminjam vrednosti funkcij. Nekaj dela je še na vožnji potem sem pa končal :D

MMG kdo poleg mene in @borut_sloja ima še z21 (če sem lahko radoveden)?

Vrni se na

Kdo je na strani

Po forumu brska: 0 registriranih uporabnikov in 3 gostov