Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion examples/mcp2515/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ func main() {
SDI: machine.SPI0_SDI_PIN,
Mode: 0})
can := mcp2515.New(spi, csPin)
can.Configure()
can.Configure(mcp2515.Configuration{})
err := can.Begin(mcp2515.CAN500kBps, mcp2515.Clock8MHz)
if err != nil {
failMessage(err.Error())
Expand Down
86 changes: 45 additions & 41 deletions mcp2515/mcp2515.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
package mcp2515 // import "tinygo.org/x/drivers/mcp2515"

import (
"encoding/binary"
"errors"
"fmt"
"time"
Expand All @@ -15,15 +16,30 @@ import (
"tinygo.org/x/drivers/internal/pin"
)

var (
ErrNothingIsReceived = errors.New("readMsg: nothing is received")
ErrRequestNewModeMaxTimeEx = errors.New("requestNewMode max time expired")
ErrLengthIsLongerThanCapacity = errors.New("length is longer than capacity")
ErrTxTimeout = errors.New("Tx: Tx timeout")
ErrInvalidDirection = errors.New("invalid direction")
ErrInvalidParameter = errors.New("invalid parameter")
ErrCannotExpandBuffer = errors.New("cannot expand buffer (to avoid memory allocation)")
)

// Device wraps MCP2515 SPI CAN Module.
type Device struct {
spi SPI
cs pin.OutputFunc
msg *CANMsg
extended bool
mcpMode byte
configurePins func()
}

type Configuration struct {
Extended bool
}

// CANMsg stores CAN message fields.
type CANMsg struct {
ID uint32
Expand Down Expand Up @@ -56,10 +72,11 @@ func New(b drivers.SPI, csPin pin.Output) *Device {
}

// Configure sets up the device for communication.
func (d *Device) Configure() {
func (d *Device) Configure(cfg Configuration) {
if d.configurePins == nil {
panic(legacy.ErrConfigBeforeInstantiated)
}
d.extended = cfg.Extended
d.configurePins()
}

Expand Down Expand Up @@ -117,9 +134,13 @@ func (d *Device) Tx(canid uint32, dlc uint8, data []byte) error {
timeoutCount++
}
if timeoutCount == timeoutvalue {
return fmt.Errorf("Tx: Tx timeout")
return ErrTxTimeout
}
err = d.writeCANMsg(bufNum, canid, 0, 0, dlc, data)
ext := byte(0)
if d.extended {
ext = 1
}
err = d.writeCANMsg(bufNum, canid, ext, 0, dlc, data)
if err != nil {
return err
}
Expand Down Expand Up @@ -389,7 +410,7 @@ func (d *Device) configRate(speed, clock byte) error {
set = false
}
if !set {
return errors.New("invalid parameter")
return ErrInvalidParameter
}
if err := d.setRegister(mcpCNF1, cfg1); err != nil {
return err
Expand Down Expand Up @@ -449,7 +470,7 @@ func (d *Device) readMsg() error {
return err
}
} else {
return fmt.Errorf("readMsg: nothing is received")
return ErrNothingIsReceived
}

return nil
Expand Down Expand Up @@ -556,39 +577,22 @@ func (d *Device) writeCANMsg(bufNum uint8, canid uint32, ext, rtrBit, dlc uint8,
}

func (s *SPI) setTxBufData(canid uint32, ext, rtrBit, dlc uint8, data []byte) error {
canid = canid & 0x0FFFF
var id [4]byte
if ext == 1 {
// TODO: add Extended ID
err := s.setTxData(0)
if err != nil {
return err
}
err = s.setTxData(0)
if err != nil {
return err
}
err = s.setTxData(0)
if err != nil {
return err
}
err = s.setTxData(0)
if err != nil {
return err
}
canid = canid & extidBottom29Mask
extended_id := canid
high_11 := extended_id & extidTop11WriteMask
low_18 := extended_id & extidBottom18Mask
high_11 <<= 3
extended_id_shifted := high_11 | low_18
canid = extended_id_shifted | extidFlagMask
} else {
err := s.setTxData(byte(canid >> 3))
if err != nil {
return err
}
err = s.setTxData(byte((canid & 0x07) << 5))
if err != nil {
return err
}
err = s.setTxData(0)
if err != nil {
return err
}
err = s.setTxData(0)
canid = canid & stdidBottom11Mask
canid <<= 16 + 5
}
binary.BigEndian.PutUint32(id[:], canid)
for _, b := range id {
err := s.setTxData(b)
if err != nil {
return err
}
Expand Down Expand Up @@ -785,7 +789,7 @@ func (d *Device) requestNewMode(newMode byte) error {
if r&modeMask == newMode {
return nil
} else if e := time.Now(); e.Sub(s) > 200*time.Millisecond {
return errors.New("requestNewMode max time expired")
return ErrRequestNewModeMaxTimeEx
}
}
}
Expand Down Expand Up @@ -861,23 +865,23 @@ func (s *SPI) clearBuffer(dir int) error { return s.setBufferLength(0, dir) }
func (s *SPI) setBufferLength(length int, dir int) error {
if dir == tx {
if length > cap(s.tx) {
return fmt.Errorf("length is longer than capacity")
return ErrLengthIsLongerThanCapacity
}
s.tx = s.tx[:length]
} else if dir == rx {
if length > cap(s.rx) {
return fmt.Errorf("length is longer than capacity")
return ErrLengthIsLongerThanCapacity
}
s.rx = s.rx[:length]
} else {
return fmt.Errorf("invalid direction")
return ErrInvalidDirection
}
return nil
}

func (s *SPI) setTxData(data byte) error {
if len(s.tx) >= bufferSize {
return fmt.Errorf("cannot expand buffer (to avoid memory allocation)")
return ErrCannotExpandBuffer
}
s.tx = append(s.tx, data)

Expand Down
7 changes: 7 additions & 0 deletions mcp2515/registers.go
Original file line number Diff line number Diff line change
Expand Up @@ -417,4 +417,11 @@ const (
canFail = 0xff

canMaxCharInMessage = 8

// for extended id
extidTop11WriteMask = 0x1FFC0000
extidBottom29Mask = (1 << 29) - 1 // extended id bits
extidBottom18Mask = (1 << 18) - 1 // bottom 18 bits
stdidBottom11Mask = 0x7FF
extidFlagMask = 1 << 19
)