Skip to content

Commit

Permalink
AVR optimisations
Browse files Browse the repository at this point in the history
  • Loading branch information
ysoldak committed Jul 8, 2024
1 parent 6cefb46 commit 2390a19
Show file tree
Hide file tree
Showing 4 changed files with 114 additions and 49 deletions.
49 changes: 0 additions & 49 deletions adapter.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,19 +135,6 @@ func (a *Adapter) Receive() (*Message, error) {
}
}

// Wait for a message with the given command and direction.
func (a *Adapter) Wait(command Command, direction Direction, timeout time.Duration) (*Message, error) {
start := time.Now()
for time.Since(start) < timeout {
message, _ := a.Receive()
// wait for correct message
if message != nil && message.Command == command && message.Direction == direction {
return message, nil
}
}
return nil, ErrTimeout
}

// Reset the state machine and clear the message buffer.
func (a *Adapter) Reset() {
a.state = stateIdle
Expand All @@ -160,39 +147,3 @@ func (a *Adapter) Reset() {
}
}
}

// BeaconTime returns the next time when a beacon with the given ID should be broadcasted.
func (a *Adapter) BeaconTime(id byte) time.Time {
if a.beaconReferenceTime == 0 {
return time.Time{}
}
offset := beaconOffset(id)
t := a.beaconReferenceTime + offset.Milliseconds()
now := time.Now().UnixMilli()
for t < now {
t += BeaconInterval.Milliseconds()
}
return time.UnixMilli(t)
}

func (a *Adapter) handleBeaconMaybe(message *Message) {
if message.Command != CmdBeacon {
return
}
id := message.Payload[0]
if a.lowestID == 0 || a.lowestID > id {
a.lowestID = id
}
if id != a.lowestID {
return
}
// The beacon with the lowest ID is the reference beacon.
offset := beaconOffset(a.lowestID)
a.beaconReferenceTime = time.Now().UnixMilli() - offset.Milliseconds()
}

func beaconOffset(id byte) time.Duration {
team := (id << 4) - 0x0A
player := (id & 0x0F) - 1
return time.Duration(team)*time.Second + time.Duration(player)*100*time.Millisecond
}
52 changes: 52 additions & 0 deletions adapter_avr.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
//go:build avr

package csp

// Wait for a message with the given command and direction.
func (a *Adapter) Wait(command Command, direction Direction, timeout int64) (*Message, error) {
start := runtime_nanotime()
for runtime_nanotime()-start < timeout {
message, _ := a.Receive()
// wait for correct message
if message != nil && message.Command == command && message.Direction == direction {
return message, nil
}
}
return nil, ErrTimeout
}

// BeaconTime returns the next time when a beacon with the given ID should be broadcasted.
func (a *Adapter) BeaconTime(id byte) int64 {
if a.beaconReferenceTime == 0 {
return 0
}
offset := beaconOffset(id)
t := a.beaconReferenceTime + offset
now := runtime_nanotime()
for t < now {
t += int64(BeaconInterval)
}
return t
}

func (a *Adapter) handleBeaconMaybe(message *Message) {
if message.Command != CmdBeacon {
return
}
id := message.Payload[0]
if a.lowestID == 0 || a.lowestID > id {
a.lowestID = id
}
if id != a.lowestID {
return
}
// The beacon with the lowest ID is the reference beacon.
offset := beaconOffset(a.lowestID)
a.beaconReferenceTime = runtime_nanotime() - offset
}

func beaconOffset(id byte) int64 {
team := (id << 4) - 0x0A
player := (id & 0x0F) - 1
return int64(team)*1_000_000_000 + int64(player)*100_000_000
}
54 changes: 54 additions & 0 deletions adapter_common.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
//go:build !avr

package csp

import "time"

// Wait for a message with the given command and direction.
func (a *Adapter) Wait(command Command, direction Direction, timeout time.Duration) (*Message, error) {
start := time.Now()
for time.Since(start) < timeout {
message, _ := a.Receive()
// wait for correct message
if message != nil && message.Command == command && message.Direction == direction {
return message, nil
}
}
return nil, ErrTimeout
}

// BeaconTime returns the next time when a beacon with the given ID should be broadcasted.
func (a *Adapter) BeaconTime(id byte) time.Time {
if a.beaconReferenceTime == 0 {
return time.Time{}
}
offset := beaconOffset(id)
t := a.beaconReferenceTime + offset.Milliseconds()
now := time.Now().UnixMilli()
for t < now {
t += BeaconInterval.Milliseconds()
}
return time.UnixMilli(t)
}

func (a *Adapter) handleBeaconMaybe(message *Message) {
if message.Command != CmdBeacon {
return
}
id := message.Payload[0]
if a.lowestID == 0 || a.lowestID > id {
a.lowestID = id
}
if id != a.lowestID {
return
}
// The beacon with the lowest ID is the reference beacon.
offset := beaconOffset(a.lowestID)
a.beaconReferenceTime = time.Now().UnixMilli() - offset.Milliseconds()
}

func beaconOffset(id byte) time.Duration {
team := (id << 4) - 0x0A
player := (id & 0x0F) - 1
return time.Duration(team)*time.Second + time.Duration(player)*100*time.Millisecond
}
8 changes: 8 additions & 0 deletions runtime.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
//go:build avr

package csp

import _ "unsafe" // for go:linkname to work

//go:linkname runtime_nanotime runtime.nanotime
func runtime_nanotime() int64

0 comments on commit 2390a19

Please sign in to comment.