diff --git a/examples/mcp2515/main.go b/examples/mcp2515/main.go index 6b7a84f1a..739ecf2f3 100644 --- a/examples/mcp2515/main.go +++ b/examples/mcp2515/main.go @@ -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()) diff --git a/mcp2515/mcp2515.go b/mcp2515/mcp2515.go index ac08b5a68..2b0309687 100644 --- a/mcp2515/mcp2515.go +++ b/mcp2515/mcp2515.go @@ -6,6 +6,7 @@ package mcp2515 // import "tinygo.org/x/drivers/mcp2515" import ( + "encoding/binary" "errors" "fmt" "time" @@ -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 @@ -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() } @@ -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 } @@ -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 @@ -449,7 +470,7 @@ func (d *Device) readMsg() error { return err } } else { - return fmt.Errorf("readMsg: nothing is received") + return ErrNothingIsReceived } return nil @@ -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 } @@ -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 } } } @@ -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) diff --git a/mcp2515/registers.go b/mcp2515/registers.go index 6b7f28a99..9ca666164 100644 --- a/mcp2515/registers.go +++ b/mcp2515/registers.go @@ -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 )