2016-02-28 78 views
5

我需要形成一個20字節的數據包,並通過藍牙將有效載荷發送到硬件外設。如何在Swift中使用位操作?

這20字節的數據包內部分爲14個數據集,每個11位,最後6位應該是空字符。

因此,總計: 160位(20個字節)= 14(套)* 11(比特)+ 6(空字符)

的11位被再次分成3組2位,3位和6位。然而,這對主要問題並不重要,我現在可以通過採用'Int16'來形成11位。我會做移位操作來過濾11位,我知道這一點。

如果我只有一個數據集,那麼我應該填寫所有20個字節,除了前面的11位空字符,如果兩個數據集,然後除了22位之外的所有應該是空字符和分別。

我面臨的問題是形成這個連續的160位,因爲奇數位是11.我想採取一個'詮釋'和做移位(< <)操作,然後按位或(|)但Int是64位。

目前我認爲採取20個固定大小的字符數組將適合這種情況。儘管在概念上我認爲這是最好的方式,但我無法通過所有條件來實現這一目標。我想我需要把所有的邏輯放在一個循環中。

任何人都可以告訴是否實現這一目標的正確方法,並指導我解決它,如果這是最好的方法。如果有的話,或者指出其他任何方式。

回答

1

您不需要將所有數據集打包成20字節的數組,直到最後,因此請將它們保存在長度爲14的Int數組中。使用這種方式更容易。當您需要通過將其發送至硬件,將其轉換爲UInt8數組長度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() 

有很多移位操作回事,所以我無法解釋這一切。一般的理想是將這11位數據集中的每一個分配到字節中,並根據需要溢出到下一個字節。

+0

謝謝你的詳細代碼。我把代碼放入遊樂場,並嘗試了幾個樣本測試,它運行良好,我也瞭解完整的代碼。再次感謝你。 :) –

1

通過代碼的不同提出的解決方案的一種變體:

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 
    } 
}