2016-02-28 18 views
5

Tôi cần phải tạo một gói dữ liệu 20 byte và gửi tải trọng tới phần cứng ngoại vi qua bluetooth.Làm thế nào để làm việc với các thao tác bit trong Swift?

Gói dữ liệu 20 byte này được chia thành 14 tập dữ liệu nội bộ, mỗi bit 11 bit, 6 bit cuối cùng phải là ký tự rỗng.

Do đó, Tổng số: 160 bit (20 byte) = 14 (bộ) * 11 (bit) + 6 (ký tự null)

Bit 11 một lần nữa chia thành 3 bộ 2 bit, 3 bit và 6 bit. Tuy nhiên nó không quan trọng đối với câu hỏi chính, tôi hiện đang có thể tạo 11 bit, bằng cách lấy 'Int16'. Tôi sẽ thực hiện thao tác dịch chuyển để lọc 11 bit, tôi biết điều đó.

Nếu tôi chỉ có một tập dữ liệu thì tôi phải điền tất cả 20 byte ngoại trừ 11 bit đầu tiên với ký tự rỗng, nếu hai tập dữ liệu thì tất cả ngoại trừ 22 bit phải là ký tự rỗng và tương ứng.

Vấn đề tôi đang gặp phải là tạo ra 160 bit tuần tự này bởi vì các bit lẻ là 11. Tôi đã nghĩ đến việc thực hiện thao tác 'Int' và làm shift (< <) và sau đó thực hiện bitwise OR (|) nhưng một Int là 64 bit.

Hiện tại tôi nghĩ việc lấy một mảng ký tự có kích thước cố định là 20 sẽ phù hợp với tình huống này. Mặc dù về mặt khái niệm tôi nghĩ đó là cách tốt nhất có thể, lập trình tôi không thể hình thành logic với tất cả các điều kiện để đạt được điều này. Tôi nghĩ rằng tôi cần phải đặt tất cả các logic trong một vòng lặp.

Bất cứ ai cũng có thể nói đó là cách phù hợp để đạt được điều này và hướng dẫn tôi giải quyết nó, nếu đây là cách tốt nhất. Hoặc chỉ ra bất kỳ cách nào khác nếu có.

Trả lời

1

Bạn không cần đóng gói tất cả bộ dữ liệu vào mảng 20 byte cho đến khi kết thúc để giữ chúng trong một mảng có chiều dài là Int 14. Dễ dàng hơn để làm việc theo cách đó. Khi bạn cần phải gửi nó cho phần cứng, chuyển nó sang một mảng UInt8 chiều dài 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() 

Có rất nhiều thay đổi các hoạt động đang diễn ra vì vậy tôi không thể giải thích tất cả. Lý tưởng chung là phân bổ từng bộ dữ liệu 11 bit đó thành các byte, tràn sang byte tiếp theo nếu cần.

+0

Cảm ơn bạn đã mã chi tiết. Tôi đặt mã vào sân chơi và thử vài bài kiểm tra mẫu, nó hoạt động tốt và tôi cũng hiểu được mã hoàn chỉnh. Cảm ơn bạn rất nhiều lần nữa. :) –

1

Một biến thể của giải pháp do Bộ luật khác nhau đề xuất:

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 
    } 
} 
Các vấn đề liên quan