mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-03 02:27:48 +00:00
318 lines
9.0 KiB
Go
318 lines
9.0 KiB
Go
package usb
|
|
|
|
//go:linkname ticks runtime.ticks
|
|
func ticks() int64
|
|
|
|
// leU64 returns a slice containing 8 bytes from the given uint64 u.
|
|
//
|
|
// The returned bytes have little-endian ordering; that is, the first element
|
|
// at index 0 is the least-significant byte in u and index 7 is the most-
|
|
// significant byte.
|
|
//go:inline
|
|
func leU64(u uint64) []uint8 {
|
|
var b [8]uint8
|
|
if u == 0 {
|
|
// skip all processing for the common case (u = 0)
|
|
return b[:]
|
|
}
|
|
b[0] = uint8(u)
|
|
b[1] = uint8(u >> 8)
|
|
b[2] = uint8(u >> 16)
|
|
b[3] = uint8(u >> 24)
|
|
b[4] = uint8(u >> 32)
|
|
b[5] = uint8(u >> 40)
|
|
b[6] = uint8(u >> 48)
|
|
b[7] = uint8(u >> 56)
|
|
return b[:]
|
|
}
|
|
|
|
// leU32 returns a slice containing 4 bytes from the given uint32 u.
|
|
//
|
|
// The returned bytes have little-endian ordering; that is, the first element
|
|
// at index 0 is the least-significant byte in u and index 3 is the most-
|
|
// significant byte.
|
|
//go:inline
|
|
func leU32(u uint32) []uint8 {
|
|
var b [4]uint8
|
|
if u == 0 {
|
|
// skip all processing for the common case (u = 0)
|
|
return b[:]
|
|
}
|
|
b[0] = uint8(u)
|
|
b[1] = uint8(u >> 8)
|
|
b[2] = uint8(u >> 16)
|
|
b[3] = uint8(u >> 24)
|
|
return b[:]
|
|
}
|
|
|
|
// leU16 returns a slice containing 2 bytes from the given uint16 u.
|
|
//
|
|
// The returned bytes have little-endian ordering; that is, the first element
|
|
// at index 0 is the least-significant byte in u and index 1 is the most-
|
|
// significant byte.
|
|
//go:inline
|
|
func leU16(u uint16) []uint8 {
|
|
var b [2]uint8
|
|
if u == 0 {
|
|
// skip all processing for the common case (u = 0)
|
|
return b[:]
|
|
}
|
|
b[0] = uint8(u)
|
|
b[1] = uint8(u >> 8)
|
|
return b[:]
|
|
}
|
|
|
|
// beU64 returns a slice containing 8 bytes from the given uint64 u.
|
|
//
|
|
// The returned bytes have big-endian ordering; that is, the first element at
|
|
// index 0 is the most-significant byte in u and index 7 is the least-
|
|
// significant byte.
|
|
//go:inline
|
|
func beU64(u uint64) []uint8 {
|
|
var b [8]uint8
|
|
if u == 0 {
|
|
// skip all processing for the common case (u = 0)
|
|
return b[:]
|
|
}
|
|
b[7] = uint8(u)
|
|
b[6] = uint8(u >> 8)
|
|
b[5] = uint8(u >> 16)
|
|
b[4] = uint8(u >> 24)
|
|
b[3] = uint8(u >> 32)
|
|
b[2] = uint8(u >> 40)
|
|
b[1] = uint8(u >> 48)
|
|
b[0] = uint8(u >> 56)
|
|
return b[:]
|
|
}
|
|
|
|
// beU32 returns a slice containing 4 bytes from the given uint32 u.
|
|
//
|
|
// The returned bytes have big-endian ordering; that is, the first element at
|
|
// index 0 is the most-significant byte in u and index 3 is the least-
|
|
// significant byte.
|
|
//go:inline
|
|
func beU32(u uint32) []uint8 {
|
|
var b [4]uint8
|
|
if u == 0 {
|
|
// skip all processing for the common case (u = 0)
|
|
return b[:]
|
|
}
|
|
b[3] = uint8(u)
|
|
b[2] = uint8(u >> 8)
|
|
b[1] = uint8(u >> 16)
|
|
b[0] = uint8(u >> 24)
|
|
return b[:]
|
|
}
|
|
|
|
// beU16 returns a slice containing 2 bytes from the given uint16 u.
|
|
//
|
|
// The returned bytes have big-endian ordering; that is, the first element at
|
|
// index 0 is the most-significant byte in u and index 1 is the least-
|
|
// significant byte.
|
|
//go:inline
|
|
func beU16(u uint16) []uint8 {
|
|
var b [2]uint8
|
|
if u == 0 {
|
|
// skip all processing for the common case (u = 0)
|
|
return b[:]
|
|
}
|
|
b[1] = uint8(u)
|
|
b[0] = uint8(u >> 8)
|
|
return b[:]
|
|
}
|
|
|
|
// revU64 returns the given uint64 u with bytes in the reverse order.
|
|
//go:inline
|
|
func revU64(u uint64) uint64 {
|
|
if u == 0 {
|
|
// skip all processing for the common case (u = 0)
|
|
return 0
|
|
}
|
|
return ((u & 0x00000000000000FF) << 56) |
|
|
((u & 0x000000000000FF00) << 40) |
|
|
((u & 0x0000000000FF0000) << 24) |
|
|
((u & 0x00000000FF000000) << 8) |
|
|
((u & 0x000000FF00000000) >> 8) |
|
|
((u & 0x0000FF0000000000) >> 24) |
|
|
((u & 0x00FF000000000000) >> 40) |
|
|
((u & 0xFF00000000000000) >> 56)
|
|
}
|
|
|
|
// revU32 returns the given uint32 u with bytes in the reverse order.
|
|
//go:inline
|
|
func revU32(u uint32) uint32 {
|
|
if u == 0 {
|
|
// skip all processing for the common case (u = 0)
|
|
return 0
|
|
}
|
|
return ((u & 0x000000FF) << 24) | ((u & 0x0000FF00) << 8) |
|
|
((u & 0x00FF0000) >> 8) | ((u & 0xFF000000) >> 24)
|
|
}
|
|
|
|
// revU16 returns the given uint16 u with bytes in the reverse order.
|
|
//go:inline
|
|
func revU16(u uint16) uint16 {
|
|
if u == 0 {
|
|
// skip all processing for the common case (u = 0)
|
|
return 0
|
|
}
|
|
return ((u & 0x00FF) << 8) | ((u & 0xFF00) >> 8)
|
|
}
|
|
|
|
// packU64 returns a uint64 constructed by concatenating the bytes in slice b.
|
|
//
|
|
// The least-significant byte in the returned value is the first element at
|
|
// index 0 in b and the most significant byte is index 7, if given. If fewer
|
|
// than 8 elements are given in b, the corresponding bytes in the returned value
|
|
// are all 0.
|
|
//go:inline
|
|
func packU64(b []uint8) (u uint64) {
|
|
for i := 0; i < 8 && i < len(b); i++ {
|
|
u |= uint64(b[i]) << (i * 8)
|
|
}
|
|
return
|
|
}
|
|
|
|
// packU32 returns a uint32 constructed by concatenating the bytes in slice b.
|
|
//
|
|
// The least-significant byte in the returned value is the first element at
|
|
// index 0 in b and the most significant byte is index 3, if given. If fewer
|
|
// than 4 elements are given in b, the corresponding bytes in the returned value
|
|
// are all 0.
|
|
//go:inline
|
|
func packU32(b []uint8) (u uint32) {
|
|
for i := 0; i < 4 && i < len(b); i++ {
|
|
u |= uint32(b[i]) << (i * 8)
|
|
}
|
|
return
|
|
}
|
|
|
|
// packU16 returns a uint16 constructed by concatenating the bytes in slice b.
|
|
//
|
|
// The least-significant byte in the returned value is the first element at
|
|
// index 0 in b and the most significant byte is index 1, if given. If fewer
|
|
// than 2 elements are given in b, the corresponding bytes in the returned value
|
|
// are all 0.
|
|
//go:inline
|
|
func packU16(b []uint8) (u uint16) {
|
|
for i := 0; i < 2 && i < len(b); i++ {
|
|
u |= uint16(b[i]) << (i * 8)
|
|
}
|
|
return
|
|
}
|
|
|
|
// msU8 returns the most-significant byte of u.
|
|
//go:inline
|
|
func msU8(u uint16) uint8 { return uint8(u >> 8) }
|
|
|
|
// lsU8 returns the least-significant byte of u.
|
|
//go:inline
|
|
func lsU8(u uint16) uint8 { return uint8(u) }
|
|
|
|
// cycles converts the given number of microseconds to CPU cycles for a CPU with
|
|
// given frequency.
|
|
//go:inline
|
|
func cycles(microsec, cpuFreqHz uint32) uint32 {
|
|
return uint32((uint64(microsec) * uint64(cpuFreqHz)) / 1000000)
|
|
}
|
|
|
|
//go:inline
|
|
func unpackEndpoint(address uint8) (number, direction uint8) {
|
|
return (address & descEndptAddrNumberMsk) >> descEndptAddrNumberPos,
|
|
(address & descEndptAddrDirectionMsk) >> descEndptAddrDirectionPos
|
|
}
|
|
|
|
//go:inline
|
|
func rxEndpoint(number uint8) uint8 {
|
|
return (number & descEndptAddrNumberMsk) | descEndptAddrDirectionOut
|
|
}
|
|
|
|
//go:inline
|
|
func txEndpoint(number uint8) uint8 {
|
|
return (number & descEndptAddrNumberMsk) | descEndptAddrDirectionIn
|
|
}
|
|
|
|
//go:inline
|
|
func endpointIndex(address uint8) uint8 {
|
|
return ((address & descEndptAddrNumberMsk) << 1) |
|
|
((address & descEndptAddrDirectionMsk) >> descEndptAddrDirectionPos)
|
|
}
|
|
|
|
//go:inline
|
|
func indexEndpoint(index uint8) uint8 {
|
|
return ((index >> 1) & descEndptAddrNumberMsk) |
|
|
((index & 0x1) << descEndptAddrDirectionPos)
|
|
}
|
|
|
|
// wrap computes the index into a circular buffer of length mod by walking
|
|
// forward n elements if n is positive, or reverse n elements if n is negative.
|
|
// For example, both wrap(42, 10) and wrap(-308, 10) return 2.
|
|
//go:inline
|
|
func wrap(n, mod int) int {
|
|
if mod <= 0 || n == mod {
|
|
return 0
|
|
}
|
|
if n < 0 {
|
|
if -n < mod {
|
|
return mod + n
|
|
}
|
|
return mod - (-n % mod)
|
|
}
|
|
if n < mod {
|
|
return n
|
|
}
|
|
return n % mod
|
|
}
|
|
|
|
// The following buffLo and buffHi are helper methods for slice definitions from
|
|
// potentially zero-length arrays (depending on compile-time constants).
|
|
//
|
|
// For example, if we have an array containing a 5-element buffer for three
|
|
// instances of some device class (15 total elements), partitioned as follows,
|
|
// then we compute the indices for instance 2 as usual:
|
|
//
|
|
// Index: 01234 56789 ABCDE
|
|
// Array: [ 1 | 2 | 3 ]
|
|
//
|
|
// Lo: (n-1) * size => (2-1) * 5 => 5
|
|
// Hi: (n) * size => (2) * 5 => 10 (0xA)
|
|
//
|
|
// However, if we have specified (via const definition) that 0 instances of some
|
|
// device class be allocated, then the associated device class buffer arrays
|
|
// will all be zero-length arrays, and the arithmetic to compute the slice
|
|
// indices used above will result in out-of-bounds indices:
|
|
//
|
|
// Index:
|
|
// Array: []
|
|
//
|
|
// Lo: (n-1) * size => (2-1) * 5 => 5 [Error!]
|
|
// Hi: (n) * size => (2) * 5 => 10 (0xA) [Error!]
|
|
//
|
|
//
|
|
// I couldn't figure out a straight-forward way to resolve these slice indices
|
|
// using only arithmetic, so I've resorted to simple conditionals. If the number
|
|
// of instances for some given class is zero (count=0), defined via compile-time
|
|
// constant, then just use the empty slice range [0:0].
|
|
|
|
// buffLo returns the starting array slice index for the n'th region of size
|
|
// elements from an array containing count regions of size elements.
|
|
// Regions are specified using a 1-based index (n > 0). Returns 0 if any given
|
|
// argument equals 0.
|
|
func buffLo(n, count, size uint16) uint16 {
|
|
if 0 == n || 0 == count || 0 == size {
|
|
return 0
|
|
}
|
|
return (n - 1) * size
|
|
}
|
|
|
|
// buffHi returns the ending array slice index for the n'th region of size
|
|
// elements from an array containing count regions of size elements.
|
|
// Regions are specified using a 1-based index (n > 0). Returns 0 if any given
|
|
// argument equals 0.
|
|
func buffHi(n, count, size uint16) uint16 {
|
|
if 0 == n || 0 == count || 0 == size {
|
|
return 0
|
|
}
|
|
return n * size
|
|
}
|