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