66package mcp2515 // import "tinygo.org/x/drivers/mcp2515"
77
88import (
9+ "encoding/binary"
910 "errors"
1011 "fmt"
1112 "time"
@@ -15,15 +16,30 @@ import (
1516 "tinygo.org/x/drivers/internal/pin"
1617)
1718
19+ var (
20+ ErrNothingIsReceived = errors .New ("readMsg: nothing is received" )
21+ ErrRequestNewModeMaxTimeEx = errors .New ("requestNewMode max time expired" )
22+ ErrLengthIsLongerThanCapacity = errors .New ("length is longer than capacity" )
23+ ErrTxTimeout = errors .New ("Tx: Tx timeout" )
24+ ErrInvalidDirection = errors .New ("invalid direction" )
25+ ErrInvalidParameter = errors .New ("invalid parameter" )
26+ ErrCannotExpandBuffer = errors .New ("cannot expand buffer (to avoid memory allocation)" )
27+ )
28+
1829// Device wraps MCP2515 SPI CAN Module.
1930type Device struct {
2031 spi SPI
2132 cs pin.OutputFunc
2233 msg * CANMsg
34+ extended bool
2335 mcpMode byte
2436 configurePins func ()
2537}
2638
39+ type Configuration struct {
40+ Extended bool
41+ }
42+
2743// CANMsg stores CAN message fields.
2844type CANMsg struct {
2945 ID uint32
@@ -56,10 +72,11 @@ func New(b drivers.SPI, csPin pin.Output) *Device {
5672}
5773
5874// Configure sets up the device for communication.
59- func (d * Device ) Configure () {
75+ func (d * Device ) Configure (cfg Configuration ) {
6076 if d .configurePins == nil {
6177 panic (legacy .ErrConfigBeforeInstantiated )
6278 }
79+ d .extended = cfg .Extended
6380 d .configurePins ()
6481}
6582
@@ -117,9 +134,13 @@ func (d *Device) Tx(canid uint32, dlc uint8, data []byte) error {
117134 timeoutCount ++
118135 }
119136 if timeoutCount == timeoutvalue {
120- return fmt . Errorf ( "Tx: Tx timeout" )
137+ return ErrTxTimeout
121138 }
122- err = d .writeCANMsg (bufNum , canid , 0 , 0 , dlc , data )
139+ ext := byte (0 )
140+ if d .extended {
141+ ext = 1
142+ }
143+ err = d .writeCANMsg (bufNum , canid , ext , 0 , dlc , data )
123144 if err != nil {
124145 return err
125146 }
@@ -389,7 +410,7 @@ func (d *Device) configRate(speed, clock byte) error {
389410 set = false
390411 }
391412 if ! set {
392- return errors . New ( "invalid parameter" )
413+ return ErrInvalidParameter
393414 }
394415 if err := d .setRegister (mcpCNF1 , cfg1 ); err != nil {
395416 return err
@@ -449,7 +470,7 @@ func (d *Device) readMsg() error {
449470 return err
450471 }
451472 } else {
452- return fmt . Errorf ( "readMsg: nothing is received" )
473+ return ErrNothingIsReceived
453474 }
454475
455476 return nil
@@ -556,39 +577,22 @@ func (d *Device) writeCANMsg(bufNum uint8, canid uint32, ext, rtrBit, dlc uint8,
556577}
557578
558579func (s * SPI ) setTxBufData (canid uint32 , ext , rtrBit , dlc uint8 , data []byte ) error {
559- canid = canid & 0x0FFFF
580+ var id [ 4 ] byte
560581 if ext == 1 {
561- // TODO: add Extended ID
562- err := s .setTxData (0 )
563- if err != nil {
564- return err
565- }
566- err = s .setTxData (0 )
567- if err != nil {
568- return err
569- }
570- err = s .setTxData (0 )
571- if err != nil {
572- return err
573- }
574- err = s .setTxData (0 )
575- if err != nil {
576- return err
577- }
582+ canid = canid & extidBottom29Mask
583+ extended_id := canid
584+ high_11 := extended_id & extidTop11WriteMask
585+ low_18 := extended_id & extidBottom18Mask
586+ high_11 <<= 3
587+ extended_id_shifted := high_11 | low_18
588+ canid = extended_id_shifted | extidFlagMask
578589 } else {
579- err := s .setTxData (byte (canid >> 3 ))
580- if err != nil {
581- return err
582- }
583- err = s .setTxData (byte ((canid & 0x07 ) << 5 ))
584- if err != nil {
585- return err
586- }
587- err = s .setTxData (0 )
588- if err != nil {
589- return err
590- }
591- err = s .setTxData (0 )
590+ canid = canid & stdidBottom11Mask
591+ canid <<= 16 + 5
592+ }
593+ binary .BigEndian .PutUint32 (id [:], canid )
594+ for _ , b := range id {
595+ err := s .setTxData (b )
592596 if err != nil {
593597 return err
594598 }
@@ -785,7 +789,7 @@ func (d *Device) requestNewMode(newMode byte) error {
785789 if r & modeMask == newMode {
786790 return nil
787791 } else if e := time .Now (); e .Sub (s ) > 200 * time .Millisecond {
788- return errors . New ( "requestNewMode max time expired" )
792+ return ErrRequestNewModeMaxTimeEx
789793 }
790794 }
791795}
@@ -861,23 +865,23 @@ func (s *SPI) clearBuffer(dir int) error { return s.setBufferLength(0, dir) }
861865func (s * SPI ) setBufferLength (length int , dir int ) error {
862866 if dir == tx {
863867 if length > cap (s .tx ) {
864- return fmt . Errorf ( "length is longer than capacity" )
868+ return ErrLengthIsLongerThanCapacity
865869 }
866870 s .tx = s .tx [:length ]
867871 } else if dir == rx {
868872 if length > cap (s .rx ) {
869- return fmt . Errorf ( "length is longer than capacity" )
873+ return ErrLengthIsLongerThanCapacity
870874 }
871875 s .rx = s .rx [:length ]
872876 } else {
873- return fmt . Errorf ( "invalid direction" )
877+ return ErrInvalidDirection
874878 }
875879 return nil
876880}
877881
878882func (s * SPI ) setTxData (data byte ) error {
879883 if len (s .tx ) >= bufferSize {
880- return fmt . Errorf ( "cannot expand buffer (to avoid memory allocation)" )
884+ return ErrCannotExpandBuffer
881885 }
882886 s .tx = append (s .tx , data )
883887
0 commit comments