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  }