2016-02-28 7 views
5

Ich muss ein 20-Byte-Datenpaket bilden und die Payload über Bluetooth an ein Hardware-Peripheriegerät senden.Wie arbeiten Sie mit Bit-Operationen in Swift?

Dieses 20-Byte-Datenpaket ist intern in 14 Datensätze unterteilt, jeder mit 11 Bits, die letzten 6 Bits sollten Nullzeichen sein.

Daher Total: 160 Bit (20 Byte) = 14 (Sätze) · 11 (Bit) + 6 (Nullzeichen)

Der 11-Bit wieder in 3 Sätze von 2 Bit aufgeteilt, 3 Bit und 6 Bit jeweils. Allerdings ist es nicht wichtig für die Hauptfrage, ich bin derzeit in der Lage, die 11 Bits zu bilden, indem ich ein "Int16" nehme. Ich werde die Schiebeoperation zum Filtern der 11 Bits machen, das weiß ich.

Wenn ich nur einen Datensatz habe, dann sollte ich alle 20 Bytes mit Ausnahme der ersten 11 Bits mit Nullzeichen füllen, wenn zwei Datensätze dann alle bis auf die 22 Bits Nullzeichen und jeweils sein sollten.

Das Problem, dem ich gegenüberstehe, ist die Bildung dieser sequentiellen 160 Bits wegen der ungeraden Bits, die 11 sind. Ich dachte an eine 'Int'-Operation und schalte (< <) Operation und dann bitweise ODER (|) aber ein Int ist 64 Bits.

Momentan denke ich, dass eine feste Größe von 20 Zeichen für diese Situation passen würde. Obwohl ich konzeptionell denke, dass es der bestmögliche Weg ist, bin ich programmatisch nicht in der Lage, die Logik mit allen Bedingungen zu bilden, um dies zu erreichen. Ich denke, ich muss die ganze Logik in eine Schleife bringen.

Kann jemand sagen, es ist der richtige Weg, um dies zu erreichen, und führen Sie mich auf die Lösung, wenn dies der beste Weg ist. Oder weisen Sie auf andere Wege hin, falls verfügbar.

Antwort

1

Sie müssen nicht alle Datensätze in das 20-Byte-Array bis zum Ende packen, also behalten Sie sie in einem Int Array der Länge 14. Einfacher damit zu arbeiten. Wenn Sie brauchen es zu schicken, um die Hardware über, wandelt es in ein UInt8 Array der Länge 20:

struct DataPacket { 
    var dataSets = [Int](count: 14, repeatedValue: 0) 

    func toCArray() -> [UInt8] { 
     var result = [UInt8](count: 20, repeatedValue: 0) 
     var index = 0 
     var bitsRemaining = 8 
     var offset = 0 

     for value in self.dataSets { 
      offset = 10 

      while offset >= 0 { 
       let mask = 1 << offset 
       let bit = ((value & mask) >> offset) << (bitsRemaining - 1) 
       result[index] |= UInt8(bit) 

       offset -= 1 
       bitsRemaining -= 1 
       if bitsRemaining == 0 { 
        index += 1 
        bitsRemaining = 8 
       } 
      } 
     } 

     return result 
    } 
} 

// Usage: 
var packet = DataPacket() 
packet.dataSets[0] = 0b11111111111 
packet.dataSets[1] = 0b00000000011 
// etc... 

let arr = packet.toCArray() 

Es gibt eine Menge ist Verschiebeoperationen geht, so kann ich sie alle nicht erklären. Das allgemeine Ideal besteht darin, jeden dieser 11-Bit-Datensätze in Bytes zuzuordnen, wobei er bei Bedarf auf das nächste Byte übergeht.

+0

Danke für die ausführliche Code. Ich habe den Code in Playground geschrieben und habe einige Beispieltests ausprobiert, es funktioniert gut und ich habe auch den kompletten Code verstanden. Vielen Dank nochmal. :) –

1

Eine Variante des von-Code vorgeschlagene Lösung anders:

struct DataPacket { 
    var dataSets = [Int16](count: 14, repeatedValue: 0) 

    func getPacket() -> [UInt8] { 
     var packet = [UInt8](count: 20, repeatedValue: 0) 
     var idxPacket = 0 

     for dataSet in dataSets { 
      for idxBit in 1...11 { 
       if dataSet & 1 << (11 - idxBit) != 0 { 
        packet[idxPacket/8] |= UInt8(0b1000_0000 >> (idxPacket % 8)) 
       } 
       idxPacket += 1 
      } 
     } 

     return packet 
    } 
} 
Verwandte Themen