Numero di complemento del numero decimale a 17 bit 2

1

Sto provando a convertire i decimali (0,05, -0,28, 25,00, ecc.) in un numero firmato a complemento a 17 bit 2. I dati dei parametri che sto trasmettendo sono SysEX Midi Data (per alcuni sintetizzatori esterni). I parametri dei dati sono composti da 3 byte.

Ad esempio, l'esempio fornito è il seguente:

  • I dati dei parametri per impostare il valore su -0.02 è (07 7F 70) (Dati2, Dati1, Dati0)

Mi chiedevo se qualcuno potesse darmi una guida per farlo in Java, ecco le specifiche di cui sto andando:

  • I dati dei parametri sono numeri firmati del complemento numero 17 a 2 bit
  • data2 = Numero del canale di missaggio e bit più significativi (bit 14-16) dei dati del parametro (con il formato 0xxx xyyy, dove xxxx è il canale di mix numero (0-15) e yyy sono i bit più in alto (bit 14-16) dei dati dei parametri.)

  • data1 = Bit 7-13 dei dati del parametro

  • data0 = I bit meno significativi (bit 0-6) dei dati del parametro

Quindi, ecco cosa sono in grado di dedurre finora:

  • I 3 byte sono composti da 17 bit, + i 4 bit per l'invio di # 0-15 (The Mix Channel)
  • Il 17 bit è il bit di firma?
  • Il bit di firma deve essere impostato solo se è un numero negativo, e in questo caso deve essere formattato con il complemento a 2
  • Il bit più alto per ogni byte di dati dei parametri è impostato su 0

Tenendo presente tutto questo, qualcuno può aiutarmi a capire, pubblicare o aiutarmi a scrivere una funzione per formattare questo numero a 17 bit da un valore decimale con segno? Aggiunta / sottrazione di bit binari in Java, Complementi di due, ecc ... Sarebbe molto gradito che qualcuno abbia qualche funzione di esempio, o spiegazioni!

Saluti

    
posta Mark 07.05.2013 - 20:07
fonte

2 risposte

1

Il valore è ridimensionato, quindi prima devi convertirlo in un numero intero. Un numero di complemento a due a 17 bit ha un intervallo da -2^16 a 2^16 - 1 o -65536 a 65535 . Pertanto, per -0.02 , lo moltiplichi per 65536 , che ti dà -1310 . Come sottolineato da Ingo, i valori di Java sono già nella notazione a complemento a due, quindi, fintanto che maschererai i bit superiori al bit 16, sei già a posto.

Ciò presuppone che il display passi da -1.0 a 1.0. Se il valore massimo sul display è diverso, devi dividere il -1310 di qualunque sia il valore massimo. 100 si avvicina molto al risultato dell'esempio, ma sarà diverso per i diversi parametri.

Tuttavia, i tre byte sono byte a 7 bit, ma lo abbiamo calcolato solo per byte a 8 bit, quindi devi eseguire un po 'più di viraggio per ottenere il formato desiderato:

(0x1fae2 >> 14) & 0x7f = 0x07 # First byte
(0x1fae2 >> 7)  & 0x7f = 0x75 # Second byte
 0x1fae2        & 0x7f = 0x62 # Third byte

Lascerò come esercizio per il lettore implementare la prima parte in Java. Se passi in 0x1fae2 come param , il codice di Ingo funziona per la seconda parte.

    
risposta data 07.05.2013 - 21:58
fonte
2

Supponendo che i dati dei parametri siano interi (come indicato da @ Stargazer712, 2s-complement) non ha alcun senso per i tipi non interi) il seguente dovrebbe farlo:

byte[] encode(int channel, int param) {
    byte[] data = new byte[3];
    // note that param is already 2's complement number, we only
    // need to split the bits apart (2x7 bits + 3 = 17)
    // 0x7f = 1111111 binary, so as to get 7 bits
    // 0x7  = 111 binary to get 3 bits
    data[2] = (byte) (param & 0x7f);         // lowest 7 bits
    data[1] = (byte) ((param >> 7) & 0x7f);  // next seven bits
    data[0] = (byte) ((param >> 14) & 0x7);  // 3 remaining bits
    // The channel must be placed 0xxxxyyy where xxxx are the 4 bit 
    // channel number, and the yyy are the 3 upper bits of the param.
    // Hence, make sure we have only 4 bits shifted left by 3
    data[0] |= (byte) ((channel & 0xF) << 3);
    return data;
}
    
risposta data 07.05.2013 - 21:02
fonte

Leggi altre domande sui tag