github.com/jshiv/can-go@v0.2.1-0.20210224011015-069e90e90bdf/data.go (about) 1 package can 2 3 import ( 4 "fmt" 5 "strconv" 6 7 "go.einride.tech/can/internal/reinterpret" 8 ) 9 10 const MaxDataLength = 64 11 12 // Data holds the data in a CAN frame. 13 // 14 // Layout 15 // 16 // Individual bits in the data are numbered according to the following scheme: 17 // 18 // BIT 19 // NUMBER 20 // +------+------+------+------+------+------+------+------+ 21 // | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | 22 // BYTE +------+------+------+------+------+------+------+------+ 23 // NUMBER 24 // +-----+ +------+------+------+------+------+------+------+------+ 25 // | 0 | | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | 26 // +-----+ +------+------+------+------+------+------+------+------+ 27 // | 1 | | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 28 // +-----+ +------+------+------+------+------+------+------+------+ 29 // | 2 | | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 30 // +-----+ +------+------+------+------+------+------+------+------+ 31 // | 3 | | 31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 32 // +-----+ +------+------+------+------+------+------+------+------+ 33 // | 4 | | 39 | 38 | 37 | 36 | 35 | 34 | 33 | 32 | 34 // +-----+ +------+------+------+------+------+------+------+------+ 35 // | 5 | | 47 | 46 | 45 | 44 | 43 | 42 | 41 | 40 | 36 // +-----+ +------+------+------+------+------+------+------+------+ 37 // | 6 | | 55 | 54 | 53 | 52 | 51 | 50 | 49 | 48 | 38 // +-----+ +------+------+------+------+------+------+------+------+ 39 // | 7 | | 63 | 62 | 61 | 60 | 59 | 58 | 57 | 56 | 40 // +-----+ +------+------+------+------+------+------+------+------+ 41 // 42 // Bit ranges can be manipulated using little-endian and big-endian bit ordering. 43 // 44 // Little-endian bit ranges 45 // 46 // Example range of length 32 starting at bit 29: 47 // 48 // BIT 49 // NUMBER 50 // +------+------+------+------+------+------+------+------+ 51 // | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | 52 // BYTE +------+------+------+------+------+------+------+------+ 53 // NUMBER 54 // +-----+ +------+------+------+------+------+------+------+------+ 55 // | 0 | | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | 56 // +-----+ +------+------+------+------+------+------+------+------+ 57 // | 1 | | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 58 // +-----+ +------+------+------+------+------+------+------+------+ 59 // | 2 | | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 60 // +-----+ +------+------+------+------+------+------+------+------+ 61 // | 3 | | <-------------LSb | 28 | 27 | 26 | 25 | 24 | 62 // +-----+ +------+------+------+------+------+------+------+------+ 63 // | 4 | | <-------------------------------------------------- | 64 // +-----+ +------+------+------+------+------+------+------+------+ 65 // | 5 | | <-------------------------------------------------- | 66 // +-----+ +------+------+------+------+------+------+------+------+ 67 // | 6 | | <-------------------------------------------------- | 68 // +-----+ +------+------+------+------+------+------+------+------+ 69 // | 7 | | 63 | 62 | 61 | <-MSb--------------------------- | 70 // +-----+ +------+------+------+------+------+------+------+------+ 71 // 72 // Big-endian bit ranges 73 // 74 // Example range of length 32 starting at bit 29: 75 // 76 // BIT 77 // NUMBER 78 // +------+------+------+------+------+------+------+------+ 79 // | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | 80 // BYTE +------+------+------+------+------+------+------+------+ 81 // NUMBER 82 // +-----+ +------+------+------+------+------+------+------+------+ 83 // | 0 | | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | 84 // +-----+ +------+------+------+------+------+------+------+------+ 85 // | 1 | | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 86 // +-----+ +------+------+------+------+------+------+------+------+ 87 // | 2 | | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 88 // +-----+ +------+------+------+------+------+------+------+------+ 89 // | 3 | | 31 | 30 | <-MSb--------------------------------- | 90 // +-----+ +------+------+------+------+------+------+------+------+ 91 // | 4 | | <-------------------------------------------------- | 92 // +-----+ +------+------+------+------+------+------+------+------+ 93 // | 5 | | <-------------------------------------------------- | 94 // +-----+ +------+------+------+------+------+------+------+------+ 95 // | 6 | | <-------------------------------------------------- | 96 // +-----+ +------+------+------+------+------+------+------+------+ 97 // | 7 | | <------LSb | 61 | 60 | 59 | 58 | 57 | 56 | 98 // +-----+ +------+------+------+------+------+------+------+------+ 99 type Data [MaxDataLength]byte 100 101 // UnsignedBitsLittleEndian returns the little-endian bit range [start, start+length) as an unsigned value. 102 func (d *Data) UnsignedBitsLittleEndian(start, length uint16) uint64 { 103 // pack bits into one continuous value 104 packed := d.PackLittleEndian() 105 // lsb index in the packed value is the start bit 106 lsbIndex := start 107 // shift away lower bits 108 shifted := packed >> lsbIndex 109 // mask away higher bits 110 masked := shifted & ((1 << length) - 1) 111 // done 112 return masked 113 } 114 115 // UnsignedBitsBigEndian returns the big-endian bit range [start, start+length) as an unsigned value. 116 func (d *Data) UnsignedBitsBigEndian(start, length uint16) uint64 { 117 // pack bits into one continuous value 118 packed := d.PackBigEndian() 119 // calculate msb index in the packed value 120 msbIndex := invertEndian(start) 121 // calculate lsb index in the packed value 122 lsbIndex := msbIndex - length + 1 123 // shift away lower bits 124 shifted := packed >> lsbIndex 125 // mask away higher bits 126 masked := shifted & ((1 << length) - 1) 127 // done 128 return masked 129 } 130 131 // SignedBitsLittleEndian returns little-endian bit range [start, start+length) as a signed value. 132 func (d *Data) SignedBitsLittleEndian(start, length uint16) int64 { 133 unsigned := d.UnsignedBitsLittleEndian(start, length) 134 return reinterpret.AsSigned(unsigned, length) 135 } 136 137 // SignedBitsBigEndian returns little-endian bit range [start, start+length) as a signed value. 138 func (d *Data) SignedBitsBigEndian(start, length uint16) int64 { 139 unsigned := d.UnsignedBitsBigEndian(start, length) 140 return reinterpret.AsSigned(unsigned, length) 141 } 142 143 // SetUnsignedBitsBigEndian sets the little-endian bit range [start, start+length) to the provided unsigned value. 144 func (d *Data) SetUnsignedBitsLittleEndian(start, length uint16, value uint64) { 145 // pack bits into one continuous value 146 packed := d.PackLittleEndian() 147 // lsb index in the packed value is the start bit 148 lsbIndex := start 149 // calculate bit mask for zeroing the bit range to set 150 unsetMask := ^uint64(((1 << length) - 1) << lsbIndex) 151 // calculate bit mask for setting the new value 152 setMask := value << lsbIndex 153 // calculate the new packed value 154 newPacked := packed&unsetMask | setMask 155 // unpack the new packed value into the data 156 d.UnpackLittleEndian(newPacked) 157 } 158 159 // SetUnsignedBitsBigEndian sets the big-endian bit range [start, start+length) to the provided unsigned value. 160 func (d *Data) SetUnsignedBitsBigEndian(start, length uint16, value uint64) { 161 // pack bits into one continuous value 162 packed := d.PackBigEndian() 163 // calculate msb index in the packed value 164 msbIndex := invertEndian(start) 165 // calculate lsb index in the packed value 166 lsbIndex := msbIndex - length + 1 167 // calculate bit mask for zeroing the bit range to set 168 unsetMask := ^uint64(((1 << length) - 1) << lsbIndex) 169 // calculate bit mask for setting the new value 170 setMask := value << lsbIndex 171 // calculate the new packed value 172 newPacked := packed&unsetMask | setMask 173 // unpack the new packed value into the data 174 d.UnpackBigEndian(newPacked) 175 } 176 177 // SetSignedBitsLittleEndian sets the little-endian bit range [start, start+length) to the provided signed value. 178 func (d *Data) SetSignedBitsLittleEndian(start, length uint16, value int64) { 179 d.SetUnsignedBitsLittleEndian(start, length, reinterpret.AsUnsigned(value, length)) 180 } 181 182 // SetSignedBitsBigEndian sets the big-endian bit range [start, start+length) to the provided signed value. 183 func (d *Data) SetSignedBitsBigEndian(start, length uint16, value int64) { 184 d.SetUnsignedBitsBigEndian(start, length, reinterpret.AsUnsigned(value, length)) 185 } 186 187 // Bit returns the value of the i:th bit in the data as a bool. 188 func (d *Data) Bit(i uint16) bool { 189 if i > 8*MaxDataLength-1 { 190 return false 191 } 192 // calculate which byte the bit belongs to 193 byteIndex := i / MaxDataLength 194 // calculate bit mask for extracting the bit 195 bitMask := uint8(1 << (i % MaxDataLength)) 196 // mocks the bit 197 bit := d[byteIndex]&bitMask > 0 198 // done 199 return bit 200 } 201 202 // SetBit sets the value of the i:th bit in the data. 203 func (d *Data) SetBit(i uint16, value bool) { 204 if i > 8*MaxDataLength-1 { 205 return 206 } 207 byteIndex := i / 8 208 bitIndex := i % 8 209 if value { 210 d[byteIndex] |= uint8(1 << bitIndex) 211 } else { 212 d[byteIndex] &= ^uint8(1 << bitIndex) 213 } 214 } 215 216 // PackLittleEndian packs the data into a contiguous uint64 value for little-endian signals. 217 func (d *Data) PackLittleEndian() uint64 { 218 var packed uint64 219 for i := 0; i < MaxDataLength; i++ { 220 packed |= uint64(d[i]) << (i * MaxDataLength) 221 } 222 // packed |= uint64(d[0]) << (0 * 8) 223 // packed |= uint64(d[1]) << (1 * 8) 224 // packed |= uint64(d[2]) << (2 * 8) 225 // packed |= uint64(d[3]) << (3 * 8) 226 // packed |= uint64(d[4]) << (4 * 8) 227 // packed |= uint64(d[5]) << (5 * 8) 228 // packed |= uint64(d[6]) << (6 * 8) 229 // packed |= uint64(d[7]) << (7 * 8) 230 return packed 231 } 232 233 // PackBigEndian packs the data into a contiguous uint64 value for big-endian signals. 234 func (d *Data) PackBigEndian() uint64 { 235 var packed uint64 236 for i := 0; i < MaxDataLength; i++ { 237 bitIndex := MaxDataLength - i - 1 238 packed |= uint64(d[i]) << (bitIndex * MaxDataLength) 239 } 240 // packed |= uint64(d[0]) << (7 * 8) 241 // packed |= uint64(d[1]) << (6 * 8) 242 // packed |= uint64(d[2]) << (5 * 8) 243 // packed |= uint64(d[3]) << (4 * 8) 244 // packed |= uint64(d[4]) << (3 * 8) 245 // packed |= uint64(d[5]) << (2 * 8) 246 // packed |= uint64(d[6]) << (1 * 8) 247 // packed |= uint64(d[7]) << (0 * 8) 248 return packed 249 } 250 251 // UnpackLittleEndian sets the value of d.Bytes by unpacking the provided value as sequential little-endian bits. 252 func (d *Data) UnpackLittleEndian(packed uint64) { 253 for i := 0; i < MaxDataLength; i++ { 254 d[i] = uint8(packed >> (i * MaxDataLength)) 255 } 256 // d[0] = uint8(packed >> (0 * 8)) 257 // d[1] = uint8(packed >> (1 * 8)) 258 // d[2] = uint8(packed >> (2 * 8)) 259 // d[3] = uint8(packed >> (3 * 8)) 260 // d[4] = uint8(packed >> (4 * 8)) 261 // d[5] = uint8(packed >> (5 * 8)) 262 // d[6] = uint8(packed >> (6 * 8)) 263 // d[7] = uint8(packed >> (7 * 8)) 264 } 265 266 // UnpackBigEndian sets the value of d.Bytes by unpacking the provided value as sequential big-endian bits. 267 func (d *Data) UnpackBigEndian(packed uint64) { 268 for i := 0; i < MaxDataLength; i++ { 269 bitIndex := MaxDataLength - i - 1 270 d[i] = uint8(packed >> (bitIndex * MaxDataLength)) 271 } 272 // d[0] = uint8(packed >> (7 * 8)) 273 // d[1] = uint8(packed >> (6 * 8)) 274 // d[2] = uint8(packed >> (5 * 8)) 275 // d[3] = uint8(packed >> (4 * 8)) 276 // d[4] = uint8(packed >> (3 * 8)) 277 // d[5] = uint8(packed >> (2 * 8)) 278 // d[6] = uint8(packed >> (1 * 8)) 279 // d[7] = uint8(packed >> (0 * 8)) 280 } 281 282 // invertEndian converts from big-endian to little-endian bit indexing and vice versa. 283 func invertEndian(i uint16) uint16 { 284 row := i / 8 285 col := i % 8 286 oppositeRow := MaxDataLength - 1 - row 287 bitIndex := (oppositeRow * 8) + col 288 return bitIndex 289 } 290 291 // CheckBitRangeLittleEndian checks that a little-endian bit range fits in the data. 292 func CheckBitRangeLittleEndian(frameLength, rangeStart, rangeLength uint16) error { 293 lsbIndex := rangeStart 294 msbIndex := rangeStart + rangeLength - 1 295 upperBound := frameLength * 8 296 if msbIndex >= upperBound { 297 return fmt.Errorf("bit range out of bounds [0, %v): [%v, %v]", upperBound, lsbIndex, msbIndex) 298 } 299 return nil 300 } 301 302 // CheckBitRangeBigEndian checks that a big-endian bit range fits in the data. 303 func CheckBitRangeBigEndian(frameLength, rangeStart, rangeLength uint16) error { 304 upperBound := frameLength * 8 305 if rangeStart >= upperBound { 306 return fmt.Errorf("bit range starts out of bounds [0, %v): %v", upperBound, rangeStart) 307 } 308 msbIndex := invertEndian(rangeStart) 309 lsbIndex := msbIndex - rangeLength + 1 310 end := invertEndian(lsbIndex) 311 if end >= upperBound { 312 return fmt.Errorf("bit range ends out of bounds [0, %v): %v", upperBound, end) 313 } 314 return nil 315 } 316 317 // CheckValue checks that a value fits in a number of bits. 318 func CheckValue(value uint64, bits uint16) error { 319 upperBound := uint64(1 << bits) 320 if value >= upperBound { 321 return fmt.Errorf("value out of bounds [0, %v): %v", upperBound, value) 322 } 323 return nil 324 } 325 326 // CreateCANFrame returns the CAN data as a can.Data object for decoding 327 func CreateCANFrame(bytes []byte) Data { 328 var d Data 329 bits := CanBits(bytes) 330 for i, b := range bits { 331 bit, _ := strconv.ParseBool(string(b)) 332 d.SetBit(uint16(i), bit) 333 334 } 335 return d 336 } 337 338 // CanBits creates the zig zag pattern of bits feeding into a can.Data frame 339 func CanBits(bytes []byte) string { 340 var bits string 341 for _, n := range bytes { 342 bn := fmt.Sprintf("%08b", n) 343 344 // Need to reverse the binary strings because of the definition of bit order 345 bits += reverse(bn) 346 } 347 return bits 348 } 349 350 // function to reverse strings 351 func reverse(s string) string { 352 runes := []rune(s) 353 for i, j := 0, len(runes)-1; i < j; i, j = i+1, j-1 { 354 runes[i], runes[j] = runes[j], runes[i] 355 } 356 return string(runes) 357 }