mercoledì 27 aprile 2016

Mandelbrot Assembler su Linux in FPU x87 32 bit

Calcolare l'insieme di Mandelbrot in ASM e' stata per me una specie di ossessione agli inizi degli anni 90, quando i miei amici erano presi dalla creazione di demo 4K (una competizione tra programmatori per fare vedere cosa si riusciva a creare nel limite di un eseguibile da 4K)
Grazie all'aiuto di internet (il nucleo del codice di calcolo e' stato ripreso riadattandolo da questo link) sono riuscito nel mio scopo utilizzando codice x87 per i calcoli in virgola mobile ed il terminale per la visualizzazione (l'accesso diretto alla memoria video del modo 13h della VGA e' possibile solo sotto DOS)




Il codice e' piuttosto generale e permette di generare immagini di qualsiasi grandezza (basta agire sui registri di e dx) e con una finestra di visualizzazione qualsiasi (basta agire sui parametri a,b,bb,da e db) e con una profondita' di calcolo modificabile (variabile cicli)

Il codice e' totalmente commentato
Per calcolare il valore di da e di db si prende la dimensione della finestra per esempio -1.5 e +1.5, si somma (dimensione 3) e si divide per la dimensione in pixel dello schermo da quindi assume il valore di 3/80=0.0375


Esempio con finestra (-1.5,-2/1.5,2) 80x80 pixels
------------------------------------------------------
section .data
    a:        dq    -1.5     ; minimo reale della finestra
    b:        dq    -2.0     ; minimo immaginario della finestra
    bb:      dq    -2.0    ; minimo immaginario della finestra (serve per resettare la variabile)
    da:      dq    0.0375     ; incremento parte reale ((2-(-2))/80px delta_a
    db:      dq    0.05    ; incremento parte immaginaria ((1.5-1.5))/80px delta_b
    limite:  dq    4.0    ; condizione di fuga
    cicli:    dd    255     ; numero di cicli di iterazione per ogni punto
    stella:  db '*',0    ; stella (dentro insieme Mandelbrot)
    spazio: db ' ',0    ; spazio (fuori insiemeMandelbrot)
    acapo: db 0x0a,0   

section .text

global _start                   ;serve a gcc

_start:

    mov     di,80 ; dimensione dell'asse reale in pixel sullo schermo

loop_reale:

    mov    dx,80  ; dimensione dell'asse immaginario in pixel sullo schermo

    ; calcola a = a + delta_a
    fstp    st0
    fld    qword     [a]    ; mette a in st0
    fld    qword    [da]    ; mette l'incremento di a in st1
    fadd    st0,st1        ; a+da
    fstp    qword    [a]    ; mette il risultato in a

loop_immaginario:
    ; calcola b = b + delta_b
    fld    qword     [b]    ; mette b in st0
    fld    qword    [db]    ; mette l'incremento di b in st1
    fadd    st0,st1        ; b+db
    fstp    qword     [b]    ; mette il risultato in b

    ;inizia la fase di calcolo
    fstp    st0
    fld    qword    [a]     ; mette a nello stack
    fld    qword    [b]     ; mette b nello stack

    push     ecx        ; salva il registro ecx
    mov     ecx,[cicli]    ; in ecx ci sara' il contatore dei cicli di iterazioni di calcolo. Si parte da 255

    fldZ            ; mette stack st3 = 0. Sara' utilizzato come parte reale z.r = 0
    fldZ            ; mette stack st2 = 0. Sara' utilizzato come parte immaginaria z.i = 0
    fldZ            ; mette stack st1 = 0. Sara' utilizzato come parte reale quadrata z.r^2 = 0
    fldZ            ; mette stack st0 = 0. Sara' utilizzato come parte immaginaria quadrata z.i^2 = 0

l1:                ; inizia il loop di calcolo piu' interno
    fsubp    st1,st0        ; sottrae z.i^2- e lo mette nello stack come st0.
    fadd    qword     [a]    ; aggiunge a ad st0
    fstp    st3        ; prende il valore di st3 con pop
    fmulp    st1,st0        ; moltiplica st0 ed st1 z.r*z.i
    fadd    st0,st0        ; moltiplica 2*st0 facendolo come una somma st0+st0
    fadd    qword    [b]    ; aggiunge ad st0 b ovvero 2*z.r+z.i+b

    fld    st1        ; mette st1 in st0 ovvero z.r
    fmul    st0,st0        ; quadrato di z.r
    fld    st1        ; mette st1 in st0 ovvero z.i
    fmul     st0,st0        ; quadrato di z.i
    fld    st1
    fadd    st0,st1        ; somma i due quadrati z.r^2+z.i^2
    fcomp    qword     [limite]; compara st0 con il limite di calcolo 4
    fstsw    ax        ; passa il valore di st0 al registro ax
    sahf            ; mette AH nelle flags
    jae    fine        ; se ax e' sopra il valore di 4 allora esci dal ciclo di calcolo
    dec    ecx        ; decrementa il contatore della iterazioni di calcolo
    jnz    l1        ; se ecx non e' zero continua il calcolo saltando alla label l1

fine:
    ffree    st5 ; ripulisce lo stack della FPU
    ffree    st4
    ffree    st3
    ffree    st2
    ffree    st1
    ffree     st0

    ;fase di stampa sul terminale
    push edx
    mov eax,4            ; chiamata di sistema (sys_write)
    mov ebx,1            ; File descriptor 1 - standard output
    mov edx,1          ;
    cmp ecx,0        ; controlla se si e' raggiunto il limite dei cicli di iterazione
    je stampa_stella   ; se e' zero stampa uno spazio
    mov ecx,spazio     ; punta alla variabile spazio
    jmp salta
stampa_stella:
    mov ecx,stella       ; punta alla variabile stella
salta:   
    int 80h              ; Chiama il kernel
    pop edx

    pop ecx


ritorna:
    ;controlla se siamo alla fine di un loop immaginario
    dec     dx
    cmp    dx,0
    jnz    loop_immaginario

    ; resetta la variabile immaginaria ovvero la riporta al valore minimo
    fld     qword    [bb]
    fstp    qword    [b]


    ; stampa un ritorno a capo se siamo arrivati al margine della finestra
    mov eax,4            ; (sys_write)
    mov ebx,1            ; File descriptor 1 - standard output
    mov ecx,acapo        ;
    mov edx,1
    int 80h              ; Chiama il kernel


    ;controlla se siamo alla fine di un loop reale
    dec    di
    cmp    di,0
    jnz    loop_reale

    ; Ritorna al sistema operativo
    mov     eax,1
    mov    ebx,0
    int     80h

------------------------------------------------------

L'eseguibile compilato e privato del codice di debug e' lungo attorno ai 650 bytes (sicuramente si puo' fare di meglio sia come scrittura del codice che come compattezza dell'eseguibile)

E per  concludere il ricordo del primo insieme di Mandelbrot mai visualizzato (direttamente sul calcolatore di Benoit Mandelbrot)


venerdì 22 aprile 2016

Assemby x86 e dissemblare in Linux

Un po' di appunti per compilare e decompilare in Assembler sotto Linux

La sintassi di nasm e' simile a quella di TASM ma ci sono alcuni dettagli per cui non e' sempre possibile compilare codice vecchio senza modifiche

Prima di tutto GEdit non ha preimpostata la colorazione della sintassi dei file .asm ma si puo' rimediare con i comandi
wget http://www.carminebenedetto.net/_downloads/asm-intel.lang 
sudo cp asm-intel.lang /usr/share/gtksourceview-3.0/language-specs/

per compilare il codice (compreso della tabella dei simboli per il debug)
nasm -f elf -F dwarf mand_linux.asm
ld mand_linux.o -o mand_linux


per rimuovere i codici di debug (ed ottenere un eseguibile nettamente piu' snello) si puo' aggiungere in fase di link lo switch --strip-all come segue
ld mand_linux.o -o mand_linux --strip-all

per compilare codice a 32 bit su un sistema operativo a 64 bit
nasm -f elf -F dwarf mand_linux.asm
ld -m elf_i386 mand_linux.o -o mand_linux


con nasm si possono compilare anche eseguibili DOS (i vecchi file .COM)
nasm -f bin -o mand_dos.com mand_dos.asm
dosbox mand_dos.com -exit


per compilare codice DOS in formato COM si deve aggiungere in testa al codice la linea

org 100h

il programma DOS puo' essere verificato con DOSBOX
dosbox programma.com -exit

Per decompilare o fare debugging, al posto del complicato gdb, puo' essere molto comodo usare ddd, una IDE di gdb in cui si puo' fare debug step-by-step con breakpoint (tasto destro sulla riga di codice), watch delle variabili e dei valori dei registri del processore


E' anche possibile editare direttamente il codice e ricompilare senza uscire da ddd (questa funzione mi ha creato qualche problema a dire il vero perche' la finestra di debug non sempre e' aggiornata con gli aggiornamenti del codice)

Nel caso di core dump del codice si puo' eseguire
gdb file_eseguibile file_core

seguito dal comando backtrace per capire dove si e' generato il segmentation fault. All'interno di ddd si puo' lanciare l'esecuzione (senza breakpoint), attendere il core dump e poi fare il backtrace direttamente dalla IDE

giovedì 21 aprile 2016

Stampa cartacea di un libro di Google Play??

Avendo del credito sul mio account Google generato da Google Rewards ho deciso di spenderlo in un libro di apprendimento di musica. Ovviamente, come tutti i musicisti hanno provato sulla loro pelle, e' necessario avere la copia cartacea per suonare...qualsiasi altro tipo di supporto e' scomodo, illeggibile, difficilmente personalizzabile con annotazioni etc. etc




Dopo avere comprato il libro lo ho trovato disponibile sul mio dispositivo mobile (senza peraltro diritto di recesso per non ho ben chiara quale normativa)...ok ma come lo stampo???

Sono andato sul desktop ed ho puntato su Google Books, nella mia libreria era presenta l'acquisto e sull'icona dell'ingranaggio in alto a destra compariva la dicitura Download PDF...perfetto...non troppo.

Il file in download era un file .ascm che ho scoperto di essere poco piu' che un link da dare in pasto Adobe Digital Edition per poter scaricare il Pdf vero

Facciamo anche questa..installato Adobe Digital Edition viene scaricato il pdf (su Mac viene messo in /home/Documenti/Digital Editions/) ma si tratta di un file con DRM che non permette ne' la selezione del testo ne' la stampa cartacea.

Esistono a questo punto dei programmi che permettono di rimuovere il DRM di Adobe (di cui non forniro' il link) e potrei finalmente stampare il libro.....ma e' normale una storia del genere per un libro legittimamente acquistato???

Mi sa che continuero' ad acquistare libri cartacei da Amazon e dalla libreria fisica (sempre che queste non spariscano e che amplino un po' il loro catalogo..)

mercoledì 20 aprile 2016

Leap Motion SDK

Mi sono comprato per circa 20 euro il Leap Motion su un e-commerce cinese (su Amazon costa piu' del doppio) con il dubbio che non fosse l'originale ma un clone.



Il dispositivo funziona perferttamente con i driver originali ed anche la confezione sembra corretta

Il sito web di Leap Motion riporta il pacchetto .deb per l'installazione sotto Linux e le istruzioni per Ubuntu ma funziona tranquillamente anche su Debian. Peraltro anche i requisiti minimi del sistema sono abbondantemente sorvradimesionati....il dispositivo funziona anche su un Centrino 1GHz (anche se si inizia a notare il ritardo)

dpkg -i Leap-*-.x86.deb

Dal punto di vista hardware il Leap Motion e' costituito da una coppia di telecamere ad infrarossi ad alta velocita' (200 fotogrammi al secondo) ed un illuminatore ad infrarossi. Vista la ridotta potenza dell'illuminatore il raggio d'azione del sensore e' inferiore al metro ma la risoluzione e' stimata a circa 0.7 cm


Non ho capito bene se il sensore usa la visione stereoscopica per determinare la terza dimensione oppure si tratta solo di una coppia di telecamere ed il lavoro di interpretazione e' demandato al PC e' connesso (aggiornamento: leggendo la documentazione tecnica tutto il lavoro di riconoscimento viene fatto dal PC, il sensore manda solo coppie di immagini, peraltro il Leap Motion viene riconosciuto nel syslog come un dispositivo video come una qualunque webcam)

Un aspetto da non sottovalutare e' la disponibilita' dell'SDK che si puo' scaricare direttamente da questo link.Sono previste librerie per C, Python e Unity

Ho provato ad usare l'esempio per Python (nella directory /samples) ma non riusciva a importare il modulo Leap. Ho riscritto parte del codice, evidenziato in giallo per fare il puntamento alle directory in modo corretto.
(versione ridotta con la sola posizione di pitch, roll e yaw)
--------------------------------------------------------------------------
import os, sys, thread, time,inspect,thread

sys.path += ["/usr/lib/Leap","../lib/x86","../lib"]

import Leap
from Leap import CircleGesture, KeyTapGesture, ScreenTapGesture, SwipeGesture


class SampleListener(Leap.Listener):
    finger_names = ['Thumb', 'Index', 'Middle', 'Ring', 'Pinky']
    bone_names = ['Metacarpal', 'Proximal', 'Intermediate', 'Distal']
    state_names = ['STATE_INVALID', 'STATE_START', 'STATE_UPDATE', 'STATE_END']

    def on_init(self, controller):
        print "Initialized"

    def on_connect(self, controller):
        print "Connected"

        # Enable gestures
        controller.enable_gesture(Leap.Gesture.TYPE_CIRCLE);
        controller.enable_gesture(Leap.Gesture.TYPE_KEY_TAP);
        controller.enable_gesture(Leap.Gesture.TYPE_SCREEN_TAP);
        controller.enable_gesture(Leap.Gesture.TYPE_SWIPE);

    def on_disconnect(self, controller):
        # Note: not dispatched when running in a debugger.
        print "Disconnected"

    def on_exit(self, controller):
        print "Exited"

    def on_frame(self, controller):
        # Get the most recent frame and report some basic information
        frame = controller.frame()

        # Get hands
        for hand in frame.hands:

            handType = "Left hand" if hand.is_left else "Right hand"

            print "  %s, id %d, position: %s" % (
                handType, hand.id, hand.palm_position)

            # Get the hand's normal vector and direction
            normal = hand.palm_normal
            direction = hand.direction

            # Calculate the hand's pitch, roll, and yaw angles
            print "  pitch: %f degrees, roll: %f degrees, yaw: %f degrees" % (
                direction.pitch * Leap.RAD_TO_DEG,
                normal.roll * Leap.RAD_TO_DEG,
                direction.yaw * Leap.RAD_TO_DEG)

def main():
    # Create a sample listener and controller
    listener = SampleListener()
    controller = Leap.Controller()

    # Have the sample listener receive events from the controller
    controller.add_listener(listener)

    # Keep this process running until Enter is pressed
    print "Press Enter to quit..."
    try:
        sys.stdin.readline()
    except KeyboardInterrupt:
        pass
    finally:
        # Remove the sample listener when done
        controller.remove_listener(listener)


if __name__ == "__main__":
    main()
--------------------------------------------------------------------------

La cosa incredibile e' la quantita' di informazioni fornita.
Per esempio il sensore riesce a distinguere
1) mano destra da mano sinistra
2) vettore normale della mano
3) yaw, pitch e roll della posizione della mano
4) direzione del braccio, direzione del polso
5) per ogni dito vengono forniti 4 valori per ciascuna delle giunzioni delle ossa

--------------------------------------------------------------------------
Frame id: 81414, timestamp: 1461155610589896, hands: 1, fingers: 5, tools: 0, gestures: 0
  Right hand, id 19, position: (33.206, 101.55, 31.0056)
  pitch: -0.360167 degrees, roll: -19.586099 degrees, yaw: -15.937854 degrees
  Arm direction: (-0.539341, -0.159729, -0.8268), wrist position: (56.3493, 103.269, 80.5455), elbow position: (201.971, 146.396, 303.781)
    Thumb finger, id: 190, length: 52.116371mm, width: 20.250000mm
      Bone: Metacarpal, start: (27.9765, 103.101, 92.2079), end: (27.9765, 103.101, 92.2079), direction: (0, 0, 0)
      Bone: Proximal, start: (27.9765, 103.101, 92.2079), end: (-6.82482, 100.813, 56.4951), direction: (0.697175, 0.0458273, 0.715435)
      Bone: Intermediate, start: (-6.82482, 100.813, 56.4951), end: (-30.6533, 99.3269, 32.1536), direction: (0.698872, 0.0435907, 0.713917)
      Bone: Distal, start: (-30.6533, 99.3269, 32.1536), end: (-50.3944, 104.308, 20.6123), direction: (0.843508, -0.212845, 0.493145)
    Index finger, id: 191, length: 58.807510mm, width: 19.342800mm
      Bone: Metacarpal, start: (38.8333, 118.553, 77.8819), end: (4.48218, 112.147, 13.1405), direction: (0.46692, 0.0870757, 0.880002)
      Bone: Proximal, start: (4.48218, 112.147, 13.1405), end: (-13.782, 110.943, -25.7277), direction: (0.42512, 0.0280223, 0.904703)
      Bone: Intermediate, start: (-13.782, 110.943, -25.7277), end: (-25.9697, 93.3597, -36.9743), direction: (0.504241, 0.727484, 0.465305)
      Bone: Distal, start: (-25.9697, 93.3597, -36.9743), end: (-31.1777, 77.3075, -34.3053), direction: (0.304817, 0.939512, -0.156218)
    Middle finger, id: 192, length: 67.006439mm, width: 18.997200mm
      Bone: Metacarpal, start: (49.2811, 115.897, 71.9318), end: (25.0349, 106.497, 7.19131), direction: (0.347527, 0.134729, 0.92794)
      Bone: Proximal, start: (25.0349, 106.497, 7.19131), end: (15.6093, 104.469, -40.035), direction: (0.19555, 0.0420621, 0.979791)
      Bone: Intermediate, start: (15.6093, 104.469, -40.035), end: (2.5615, 85.8319, -57.0945), direction: (0.458841, 0.655411, 0.599918)
      Bone: Distal, start: (2.5615, 85.8319, -57.0945), end: (-6.32149, 69.2732, -56.8969), direction: (0.472701, 0.88116, -0.0105194)
    Ring finger, id: 193, length: 64.428482mm, width: 18.077040mm
      Bone: Metacarpal, start: (59.6432, 110.65, 67.9288), end: (46.5165, 98.9206, 7.8132), direction: (0.209559, 0.187246, 0.9597)
      Bone: Proximal, start: (46.5165, 98.9206, 7.8132), end: (49.952, 104.128, -36.4287), direction: (-0.0768931, -0.116561, 0.990202)
      Bone: Intermediate, start: (49.952, 104.128, -36.4287), end: (42.4103, 90.7847, -59.5039), direction: (0.272243, 0.48169, 0.832981)
      Bone: Distal, start: (42.4103, 90.7847, -59.5039), end: (33.5572, 75.4563, -65.4834), direction: (0.473833, 0.820404, 0.320031)
    Pinky finger, id: 194, length: 50.510735mm, width: 16.057440mm
      Bone: Metacarpal, start: (68.5105, 99.5173, 67.8996), end: (64.7404, 88.1882, 11.157), direction: (0.065018, 0.19538, 0.97857)
      Bone: Proximal, start: (64.7404, 88.1882, 11.157), end: (75.9784, 92.3616, -22.108), direction: (-0.317824, -0.11803, 0.940775)
      Bone: Intermediate, start: (75.9784, 92.3616, -22.108), end: (74.1183, 84.4117, -39.8812), direction: (0.0951014, 0.406461, 0.908705)
      Bone: Distal, start: (74.1183, 84.4117, -39.8812), end: (66.4641, 71.7476, -48.7209), direction: (0.444062, 0.734713, 0.51284)
--------------------------------------------------------------------------

fra le altre coste e' possibile impostare anche il riconoscimento delle gesture

Selezionare testo in nano

Alcune volte puo' essere comodo fare cut and paste nell'editor Nano. Il problema e' che la combinazione di tasti per attivare la modalita' di selezione e' quanto meno curiosa ed e' CTRL+SHIF+6 (e lo dice uno che in Turbo Pascal era abituato a CTRL+K B e CTRL+K K per  aprire e chiudere i blocchi di selezione)



La selezione del testo si fa attraverso le frecce dopo aver iniziato la modalita' Selezione

Un altro aspetto curioso e' che si puo' fare strettamente Cut and Paste (con CTRL+K e CTRL+U) e non Copy and Paste

Per questo motivo se si vuole copiare una parte di codice in un altro posto si deve tagliare la parte selezionata, incollarla in posto e poi copiare di nuovo nella posizione desiderata

ps: esistono altri editor disponibili, peraltro alcuni con scorciatoie di tastiera simili a quelle di Borland che a sua volta rimandava a Wordstar (se non erro), come per esempio Joe ma non sono installati di default in Debian e si deve quindi convivere con Nano (come prima avevo convissuto con Vi)


martedì 19 aprile 2016

DGPS con Ublox M8T e RTKLib a 5Hz e 10Hz

In caso di utilizzo di GPS Differenziale in modalita' dinamica puo' essere utile avere una frequenza di campionamento piu' veloce dello standard di una acquisizione al secondo, in particolar modo se il rover si muove rapidamente.
L'Ublox M8T permette questa funzionalita' almeno fino al valore di campionamento di 10Hz (piu' veloce non ho provato ma il file di configurazione permette di inserire il tempo di campionamento in millisecondi, il che fa pensare che si posssano inserire valori inferiori ai 100 millisecondi



L'unica accortezza, per permettere il campionamento piu' veloce, e' quello di modificare la velocita' della porta seriale (anche se si acquisisce via USB) modificando il valore standard di 9600 bps portandolo a 115200 bps. Si deve tenere anche conto che il file di configurazione di RTKLib, nonostante si chiami ubx_m8t_glo_raw_5hz.cmd non modifica la velocita' della porta per cui, cosi' come e', e' sostanzialmente inutile


-----------------------------------
# RTKNAVI options (2016/02/08 17:25:54, v.2.4.3 b8)

pos1-posmode       =single     # (0:single,1:dgps,2:kinematic,3:static,4:movingbase,5:fixed,6:ppp-kine,7:ppp-static,8:ppp-fixed)
pos1-frequency     =l1         # (1:l1,2:l1+l2,3:l1+l2+l5,4:l1+l5)
pos1-soltype       =forward    # (0:forward,1:backward,2:combined)
pos1-elmask        =15         # (deg)
pos1-snrmask_r     =off        # (0:off,1:on)
pos1-snrmask_b     =off        # (0:off,1:on)
pos1-snrmask_L1    =0,0,0,0,0,0,0,0,0
pos1-snrmask_L2    =0,0,0,0,0,0,0,0,0
pos1-snrmask_L5    =0,0,0,0,0,0,0,0,0
pos1-dynamics      =off        # (0:off,1:on)
pos1-tidecorr      =off        # (0:off,1:on,2:otl)
pos1-ionoopt       =brdc       # (0:off,1:brdc,2:sbas,3:dual-freq,4:est-stec,5:ionex-tec,6:qzs-brdc,7:qzs-lex,8:stec)
pos1-tropopt       =saas       # (0:off,1:saas,2:sbas,3:est-ztd,4:est-ztdgrad,5:ztd)
pos1-sateph        =brdc       # (0:brdc,1:precise,2:brdc+sbas,3:brdc+ssrapc,4:brdc+ssrcom)
pos1-posopt1       =off        # (0:off,1:on)
pos1-posopt2       =off        # (0:off,1:on)
pos1-posopt3       =off        # (0:off,1:on,2:precise)
pos1-posopt4       =off        # (0:off,1:on)
pos1-posopt5       =off        # (0:off,1:on)
pos1-posopt6       =off        # (0:off,1:on)
pos1-exclsats      =           # (prn ...)
pos1-navsys        =1          # (1:gps+2:sbas+4:glo+8:gal+16:qzs+32:comp)
pos2-armode        =continuous # (0:off,1:continuous,2:instantaneous,3:fix-and-hold)
pos2-gloarmode     =off        # (0:off,1:on,2:autocal)
pos2-bdsarmode     =off        # (0:off,1:on)
pos2-arthres       =3
pos2-arthres1      =0.9999
pos2-arthres2      =0.25
pos2-arthres3      =0.1
pos2-arthres4      =0.05
pos2-arlockcnt     =0
pos2-arelmask      =0          # (deg)
pos2-arminfix      =10
pos2-armaxiter     =1
pos2-elmaskhold    =0          # (deg)
pos2-aroutcnt      =5
pos2-maxage        =30         # (s)
pos2-syncsol       =off        # (0:off,1:on)
pos2-slipthres     =0.05       # (m)
pos2-rejionno      =30         # (m)
pos2-rejgdop       =30
pos2-niter         =1
pos2-baselen       =0          # (m)
pos2-basesig       =0          # (m)
out-solformat      =llh        # (0:llh,1:xyz,2:enu,3:nmea)
out-outhead        =off        # (0:off,1:on)
out-outopt         =off        # (0:off,1:on)
out-timesys        =gpst       # (0:gpst,1:utc,2:jst)
out-timeform       =hms        # (0:tow,1:hms)
out-timendec       =3
out-degform        =deg        # (0:deg,1:dms)
out-fieldsep       =
out-height         =ellipsoidal # (0:ellipsoidal,1:geodetic)
out-geoid          =internal   # (0:internal,1:egm96,2:egm08_2.5,3:egm08_1,4:gsi2000)
out-solstatic      =all        # (0:all,1:single)
out-nmeaintv1      =0          # (s)
out-nmeaintv2      =0          # (s)
out-outstat        =off        # (0:off,1:state,2:residual)
stats-eratio1      =100
stats-eratio2      =100
stats-errphase     =0.003      # (m)
stats-errphaseel   =0.003      # (m)
stats-errphasebl   =0          # (m/10km)
stats-errdoppler   =1          # (Hz)
stats-stdbias      =30         # (m)
stats-stdiono      =0.03       # (m)
stats-stdtrop      =0.3        # (m)
stats-prnaccelh    =10         # (m/s^2)
stats-prnaccelv    =10         # (m/s^2)
stats-prnbias      =0.0001     # (m)
stats-prniono      =0.001      # (m)
stats-prntrop      =0.0001     # (m)
stats-prnpos       =0          # (m)
stats-clkstab      =5e-12      # (s/s)
ant1-postype       =llh        # (0:llh,1:xyz,2:single,3:posfile,4:rinexhead,5:rtcm)
ant1-pos1          =90         # (deg|m)
ant1-pos2          =0          # (deg|m)
ant1-pos3          =-6335367.6285 # (m|m)
ant1-anttype       =
ant1-antdele       =0          # (m)
ant1-antdeln       =0          # (m)
ant1-antdelu       =0          # (m)
ant2-postype       =llh        # (0:llh,1:xyz,2:single,3:posfile,4:rinexhead,5:rtcm)
ant2-pos1          =90         # (deg|m)
ant2-pos2          =0          # (deg|m)
ant2-pos3          =-6335367.6285 # (m|m)
ant2-anttype       =
ant2-antdele       =0          # (m)
ant2-antdeln       =0          # (m)
ant2-antdelu       =0          # (m)
misc-timeinterp    =off        # (0:off,1:on)
misc-sbasatsel     =0          # (0:all)
misc-rnxopt1       =
misc-rnxopt2       =
misc-pppopt        =
file-satantfile    =
file-rcvantfile    =
file-staposfile    =
file-geoidfile     =
file-ionofile      =
file-dcbfile       =
file-eopfile       =
file-blqfile       =
file-tempdir       =/tmp
file-geexefile     =
file-solstatfile   =
file-tracefile     =
file-cmdfile1      =ubx_m8t_glo_raw_10hz.cmd




inpstr1-type       =serial     # (0:off,1:serial,2:file,3:tcpsvr,4:tcpcli,7:ntripcli,8:ftp,9:http)
inpstr2-type       =off        # (0:off,1:serial,2:file,3:tcpsvr,4:tcpcli,7:ntripcli,8:ftp,9:http)
inpstr3-type       =off        # (0:off,1:serial,2:file,3:tcpsvr,4:tcpcli,7:ntripcli,8:ftp,9:http)
inpstr1-path       =ttyACM0:115200:8:n:1:off
inpstr2-path       =
inpstr3-path       =
inpstr1-format     =ubx        # (0:rtcm2,1:rtcm3,2:oem4,3:oem3,4:ubx,5:ss2,6:hemis,7:skytraq,8:gw10,9:javad,10:nvs,11:binex,12:rt17,15:sp3)
inpstr2-format     =rtcm2      # (0:rtcm2,1:rtcm3,2:oem4,3:oem3,4:ubx,5:ss2,6:hemis,7:skytraq,8:gw10,9:javad,10:nvs,11:binex,12:rt17,15:sp3)
inpstr3-format     =rtcm2      # (0:rtcm2,1:rtcm3,2:oem4,3:oem3,4:ubx,5:ss2,6:hemis,7:skytraq,8:gw10,9:javad,10:nvs,11:binex,12:rt17,15:sp3)
inpstr2-nmeareq    =off        # (0:off,1:latlon,2:single)
inpstr2-nmealat    =0          # (deg)
inpstr2-nmealon    =0          # (deg)
outstr1-type       =file       # (0:off,1:serial,2:file,3:tcpsvr,4:tcpcli,6:ntripsvr)
outstr2-type       =off        # (0:off,1:serial,2:file,3:tcpsvr,4:tcpcli,6:ntripsvr)
outstr1-path       =./ufast2.txt
outstr2-path       =
outstr1-format     =llh        # (0:llh,1:xyz,2:enu,3:nmea)
outstr2-format     =llh        # (0:llh,1:xyz,2:enu,3:nmea)
logstr1-type       =file       # (0:off,1:serial,2:file,3:tcpsvr,4:tcpcli,6:ntripsvr)
logstr2-type       =off        # (0:off,1:serial,2:file,3:tcpsvr,4:tcpcli,6:ntripsvr)
logstr3-type       =off        # (0:off,1:serial,2:file,3:tcpsvr,4:tcpcli,6:ntripsvr)
logstr1-path       =./ufast2.ubx
logstr2-path       =
logstr3-path       =
misc-svrcycle      =10         # (ms)
misc-timeout       =10000      # (ms)
misc-reconnect     =10000      # (ms)
misc-nmeacycle     =5000       # (ms)
misc-buffsize      =32768      # (bytes)
misc-navmsgsel     =all        # (0:all,1:rover,2:base,3:corr)
misc-proxyaddr     =
misc-fswapmargin   =30         # (s)

-----------------------------------

File di configurazione per acquisizione raw a 10Hz. Nella prima riga evidenziata in giallo si imposta la velocita' della seriale, nella seconda il passo di campionamento (100 ms)
-----------------------------------
!UBX CFG-GNSS 0 32 32 1 3 16 16 0 0

!UBX CFG-GNSS 0 32 32 1 6 16 16 0 1

!UBX CFG-MSG 2 21 0 0 0 1 0 0

!UBX CFG-MSG 2 19 0 0 0 1 0 0

!UBX CFG-PRT 1 0 0 2256 115200 7 7 0

!UBX CFG-RATE 100 1 1

@
!UBX CFG-MSG 2 21 0 0 0 0 0 0

!UBX CFG-MSG 2 19 0 0 0 0 0 0

!UBX CFG-RATE 100 1 1
-----------------------------------

Rtkrcv, per il post processing, si deve essere sicuri di impostare il corretto valore del passo di campionamento



Questi sono i risultati di due prove di DGPS con rover e stazione entrambi con Ublox M8T. Le condizioni di misure non erano ottimali data la presenza di palazzi ed ambiente urbano ma si ottiene comunque un fix piuttosto stabile 

Prova a 5Hz
Prova a 10Hz




Debugger integrato ESP32S3

Aggiornamento In realta' il Jtag USB funziona anche sui moduli cinesi Il problema risiede  nell'ID USB della porta Jtag. Nel modulo...