'
'  Purpose:    General Test routines for SJA1000 on the CANDIP in BasicCAN mode
'
'  Chip:       AT90S8515 running at 3.6864MHz
'
'  Version:    1.0.0, 25:th of February 2000
'
'  Author:     Lars Wictorsson
'              LAWICEL / SWEDEN
'              http://www.lawicel.com   lars@lawicel.com
'
'  Remarks:    This code sample is provided as is and demonstrates
'              simple distributed I/O by CAN. The CANDIP is reading
'              two push buttons and sends their current status as
'              CAN frames when they are changed. The NodeId used is read
'              from the CANDIP Activity board jumpers (PD3-PD5) when started.
'              When button PB2 and/or PB3 is busshed/released their status
'              is sent on the CANbus based on the NodeId read from startup.
'              The other node is "listening" for this ID and will display
'              the status on the LED's PB0 and PB1 and vice versa.
'              This demonstrates the Multi Master functionality of CAN.
'              This program is tested with BASCOM-AVR version 1.0.0.8.
'
'  Test Setup: Use 2 CANDIP's and 2 Activity boards.
'              One one Activity board, set PD3-PD5 open (NodeID=0).
'              One the other, set PD3 closed, PD4-PD5 open (NodeID=1).
'              Set PB0-PB1 as output and PB2-PB3 as input.
'
'
'  History:    2000-02-25  1.0.0   Created
'
'  CANDIP:     See CANDIP at http://www.lawicel.com/candip/
'

$crystal = 3686400
$baud = 57600

' SJA1000 CAN contoller is located at &H4000
Const Can_base = &H4000

' Some SJA1000 registers in BasicCAN mode
Const Can_ctrl = &H4000
Const Can_cmd = &H4001
Const Can_status = &H4002
Const Can_int = &H4003
Const Can_ac = &H4004
Const Can_am = &H4005
Const Can_tmg_0 = &H4006
Const Can_tmg_1 = &H4007
Const Can_ocr = &H4008
Const Can_test = &H4009
Const Can_tx_id = &H400A
Const Can_tx_len = &H400B
Const Can_tx_buf0 = &H400C
Const Can_tx_buf1 = &H400D
Const Can_tx_buf2 = &H400E
Const Can_tx_buf3 = &H400F
Const Can_tx_buf4 = &H4010
Const Can_tx_buf5 = &H4011
Const Can_tx_buf6 = &H4012
Const Can_tx_buf7 = &H4013
Const Can_rx_id = &H4014
Const Can_rx_len = &H4015
Const Can_rx_buf0 = &H4016
Const Can_rx_buf1 = &H4017
Const Can_rx_buf2 = &H4018
Const Can_rx_buf3 = &H4019
Const Can_rx_buf4 = &H401A
Const Can_rx_buf5 = &H401B
Const Can_rx_buf6 = &H401C
Const Can_rx_buf7 = &H401D
Const Can_clkdiv = &H401F

' Some key values

Const Own_id = 0                                              ' Our CAN-ID
Const Acceptmask = &HFF                                       ' Our accept mask

' Some useful bitmasks

Const Resreq = 1                                              ' Reset Request
Const Rbs = 1                                                 ' Receive Buffer Status
Const Rrb = 4                                                 ' Release Receive Buffer
Const Txreq = 1                                               ' Transmit Request
Const Tba = 4                                                 ' Transmit Buffer Access

Declare Sub Initsja
Declare Sub Transmitcanio( b as byte)
Declare Sub Checkcan

Dim Always As Byte
Dim Nodeid As Byte
Dim Inpb As Byte
Dim Inpbold As Byte

Always = 1
Inpb = &H0C                                                   ' Default button status
Inpbold = &H0C

Mcucr = &HC0                                                  ' Enable External Memory Access With Wait - state

Ddrb = &H03                                                   ' Set PB0+PB1 as output and PB2+PB3 as input with pullup
Portb = &H0F                                                  ' and turn off LED's

Ddrd = &H00                                                   ' Set PD3+PD4+PD5 as inputs with pullup
Portd = &H38

Nodeid = Pind                                                 ' Read Jumper inputs on Port D and save as Node ID.
Rotate Nodeid , Right , 3
Nodeid = Nodeid And &H07
Nodeid = 7 -  Nodeid                                          ' Invert, how to make it better in BASCOM?

Initsja

While Always = 1
  Inpb = Pinb And &H0C                                        ' Read inputs PB2 & PB3

  If Inpb <> Inpbold Then                                     ' Are they different from last check?
    Transmitcanio Inpb                                        ' If so, send new state of buttons
    Inpbold = Inpb                                            ' and save this state
  End If
  Checkcan
Wend

End

Sub Initsja                                                   ' Initiate CAN controller 125kbit
  Local B As Byte
  B = Inp(can_ctrl)
  B = B And Resreq
  While B = 0
    out can_ctrl,resreq
    B = Inp(can_ctrl)
    B = B And Resreq
  Wend
  out Can_ac, Own_id
  out Can_am, Acceptmask
  out Can_tmg_0,3
  out Can_tmg_1,&H1C
  out Can_ocr,&HDE
  out Can_clkdiv,7
  out Can_ctrl,&H5E
  out Can_cmd,&H0C
End Sub

Sub Transmitcanio( b as byte)
  Local Id As Word
  Local Tmp1 As Word
  Local Ln As Byte
  Local Tmp2 As Byte

  Do                                                          ' Loop until transmit buffer is empty
    Tmp1 = Inp(can_status)
    Tmp1 = Tmp1 And Tba
  Loop Until Tmp1 = Tba

  Id = &H500 + Nodeid                                         ' Create ID based on NodeId
  Ln = 1
  Tmp1 = Id
  Rotate Tmp1 , Right , 3
  Tmp2 = Low(tmp1)
  out Can_tx_id, Tmp2
  Tmp1 = Id And &H07
  Rotate Tmp1 , Left , 5
  Tmp1 = Tmp1 + Ln
  Tmp2 = Low(tmp1)
  out Can_tx_len, Tmp2
  out Can_tx_buf0, b
  out Can_cmd, Txreq
End Sub


Sub Checkcan
  Local Id As Word
  Local Tmp1 As Word
  Local Ln As Byte
  Local Tmp2 As Byte

  Tmp2 = Inp(can_status)
  Tmp2 = Tmp2 And Rbs

  If Tmp2 = Rbs Then
    Tmp2 = Inp(can_rx_id)
    Id = Makeint(tmp2 , 0)
    Rotate Id , Left , 3
    Tmp1 = Inp(can_rx_len)
    Rotate Tmp1 , Right , 5
    Tmp1 = Tmp1 And &H07
    Id = Id + Tmp1
    Tmp2 = Inp(can_rx_len)
    Ln = Tmp2 And &H0F
    Tmp2 = Inp(can_rx_buf0)
    Rotate Tmp2 , Right , 2
    If Nodeid = 0 Then
      If Id = &H501 Then
        Portb = &H0C + Tmp2
      End If
    Elseif Nodeid = 1 Then
      If Id = &H500 Then
        Portb = &H0C + Tmp2
      End If
    End If
    out can_cmd, rrb                                          ' Release receive buffer
  End If
End Sub