-
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* device: set player number * CSP protocol update * CSP fixes * Assorted CSP fixes
- Loading branch information
Showing
8 changed files
with
348 additions
and
203 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,142 @@ | ||
package csp | ||
|
||
import ( | ||
"errors" | ||
"fmt" | ||
"machine" | ||
"time" | ||
) | ||
|
||
const DEBUG = false | ||
|
||
var ErrNoData = errors.New("No data available") | ||
var ErrWrongChecksum = errors.New("Wrong checksum") | ||
var ErrWrite = errors.New("Write failed") | ||
var ErrWriteLength = errors.New("Write failed to send all bytes") | ||
|
||
// States | ||
const ( | ||
STATE_IDLE byte = iota | ||
STATE_HEADER | ||
STATE_LENGTH | ||
STATE_COMMAND | ||
STATE_PAYLOAD | ||
STATE_CHECKSUM | ||
) | ||
|
||
type Adapter struct { | ||
uart *machine.UART | ||
|
||
state byte | ||
Message Message | ||
} | ||
|
||
func NewAdapter(uart *machine.UART) *Adapter { | ||
return &Adapter{ | ||
uart: uart, | ||
} | ||
} | ||
|
||
// Send a message. | ||
func (a *Adapter) Send(m *Message) error { | ||
bytes := m.Bytes() | ||
if DEBUG { | ||
fmt.Printf("%s SEND ", time.Now().Format("15:04:05.000")) | ||
for _, b := range bytes { | ||
fmt.Printf(" %02X", b) | ||
} | ||
fmt.Println() | ||
} | ||
n, err := a.uart.Write(bytes) | ||
if err != nil { | ||
return ErrWrite | ||
} | ||
if n != len(bytes) { | ||
return ErrWriteLength | ||
} | ||
return nil | ||
} | ||
|
||
// Receive a message; returns nil if no message is available (yet). | ||
func (a *Adapter) Receive() (*Message, error) { | ||
for { | ||
b, err := a.uart.ReadByte() | ||
if err != nil { | ||
return nil, ErrNoData | ||
} | ||
switch a.state { | ||
case STATE_IDLE: | ||
if b == '$' { | ||
if DEBUG { | ||
fmt.Printf("%s IDLE %02X\n", time.Now().Format("15:04:05.000"), b) | ||
} | ||
a.Message.Header[0] = b | ||
a.state = STATE_HEADER | ||
} | ||
case STATE_HEADER: | ||
if b == 'C' { | ||
if DEBUG { | ||
fmt.Printf("%s HEADER %02X\n", time.Now().Format("15:04:05.000"), b) | ||
} | ||
a.Message.Header[1] = b | ||
a.state = STATE_LENGTH | ||
} else { | ||
a.state = STATE_IDLE | ||
} | ||
case STATE_LENGTH: | ||
if DEBUG { | ||
fmt.Printf("%s LENGTH %02X\n", time.Now().Format("15:04:05.000"), b) | ||
} | ||
if b > MAX_PAYLOAD { | ||
a.state = STATE_IDLE | ||
continue | ||
} | ||
a.Message.Length = b | ||
a.Message.Payload = []byte{} | ||
a.Message.Checksum = b | ||
a.state = STATE_COMMAND | ||
case STATE_COMMAND: | ||
if DEBUG { | ||
fmt.Printf("%s COMMAND %02X\n", time.Now().Format("15:04:05.000"), b) | ||
} | ||
a.Message.Command = b | ||
a.Message.Checksum ^= b | ||
a.state = STATE_PAYLOAD | ||
case STATE_PAYLOAD: | ||
a.Message.Payload = append(a.Message.Payload, b) | ||
a.Message.Checksum ^= b | ||
if len(a.Message.Payload) == int(a.Message.Length) { | ||
a.state = STATE_CHECKSUM | ||
} | ||
case STATE_CHECKSUM: | ||
if DEBUG { | ||
fmt.Printf("%s PAYLOAD ", time.Now().Format("15:04:05.000")) | ||
for _, bb := range a.Message.Bytes() { | ||
fmt.Printf(" %02X", bb) | ||
} | ||
fmt.Println() | ||
fmt.Printf("%s CHECKSUM expected %02X ?= %02X actual\n", time.Now().Format("15:04:05.000"), a.Message.Checksum, b) | ||
} | ||
m := a.Message | ||
a.Message = Message{} | ||
a.state = STATE_IDLE | ||
if m.Checksum == b { | ||
return &m, nil | ||
} else { | ||
return nil, ErrWrongChecksum | ||
} | ||
} | ||
} | ||
} | ||
|
||
// Reset the state machine and clear the message buffer. | ||
func (a *Adapter) Reset() { | ||
a.state = STATE_IDLE | ||
a.Message = Message{} | ||
for { | ||
_, err := a.uart.ReadByte() | ||
if err != nil { | ||
return | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
package csp | ||
|
||
const MAX_PAYLOAD = 1 + 1 + 110 // CFG SET requests: ID, Offset, Data | ||
|
||
// Commands | ||
const ( | ||
COMMAND_BEACON byte = 0x71 // ID[1], Name[10], Description[20] | ||
|
||
COMMAND_CFG_GET_REQ byte = 0x72 // ID[1], Offset[1], Length[1] | ||
COMMAND_CFG_GET_RSP byte = 0x73 // ID[1], Offset[1], Data[<=110] | ||
COMMAND_CFG_SET_REQ byte = 0x74 // ID[1], Offset[1], Data[<=110] <-- data length = message payload length - 2 | ||
COMMAND_CFG_SET_RSP byte = 0x75 // ID[1], Offset[1], Data[<=110] <-- ID[1] can be new if team or player changed | ||
|
||
COMMAND_HIT byte = 0x82 // ID[1], Lives[1] | ||
COMMAND_CLAIM byte = 0x84 // ID[1], Power[1] | ||
) | ||
|
||
type Message struct { | ||
Header [2]byte // '$' + 'C' | ||
Length byte // Length of the payload | ||
Command byte // 0x82 = Claim, 0x83 = Hit, etc | ||
Payload []byte // Data | ||
Checksum byte // XOR of all bytes from length to the end of payload | ||
} | ||
|
||
func NewMessage(command byte, data []byte) *Message { | ||
checksum := byte(len(data)) ^ command | ||
for _, b := range data { | ||
checksum ^= b | ||
} | ||
return &Message{ | ||
Header: [2]byte{'$', 'C'}, | ||
Length: byte(len(data)), | ||
Command: command, | ||
Payload: data, | ||
Checksum: checksum, | ||
} | ||
} | ||
|
||
func (m *Message) Bytes() []byte { | ||
b := make([]byte, 4+len(m.Payload)+1) | ||
b[0] = m.Header[0] | ||
b[1] = m.Header[1] | ||
b[2] = m.Length | ||
b[3] = m.Command | ||
copy(b[4:], m.Payload) | ||
b[len(b)-1] = m.Checksum | ||
return b | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.