Revision: 1724
Author: bvwelch
Date: Sat Feb 27 17:19:52 2010
Log: CAN UART bridge adapter library

http://code.google.com/p/jallib/source/detail?r=1724

Added:
 /trunk/include/protocol/can_adapter.jal

=======================================
--- /dev/null
+++ /trunk/include/protocol/can_adapter.jal     Sat Feb 27 17:19:52 2010
@@ -0,0 +1,275 @@
+-- Title: CAN to UART adapter library
+-- Author: William Welch Copyright (c) 2010, all rights reserved.
+-- Sponsored by: Fiwihex www.fiwihex.com
+-- Compiler: 2.4m
+--
+-- This file is part of jallib (http://jallib.googlecode.com)
+-- Released under the ZLIB license (http://www.opensource.org/licenses/zlib-license.html)
+--
+-- Description: bridge/gateway between RS232 and CAN bus. Uses ASCII encapsulation,
+--          compatible with the Socket-CAN SLCAN API, and adapters such as
+--          LAWICEL and VScom USB-CAN.
+--
+-- Sources: Socket-CAN, in particular the SLCAN API. http://developer.berlios.de/projects/socketcan/
+--          also, the LAWICEL CAN-USB and Easylink adapter manuals.
+--
+-- Compatibility testing has been done using the CANHACKER tool.
+-- See http://www.canhack.de/
+--
+
+var bit can_adapter_is_open = 0
+
+-- these commands are always available
+-- this routine is primarily for internal use.
+function can_modeless_cmd(volatile byte out device, byte in ascii_buf[32]) return bit is
+   var byte cmd
+   cmd = ascii_buf[0]
+
+   -- FIXME version
+   if cmd == "V" then
+      device = "V"
+      device = "0"
+      device = "1"
+      device = "0"
+      device = "1"
+      device = 13
+      return 1
+
+      -- FIXME Serial #
+   elsif cmd == "N" then
+      device = "N"
+      for 8 loop
+         device = "9"
+      end loop
+      device = 13
+      return 1
+
+      -- FIXME 'extra information'. Seems like we can
+      -- return whatever we want here???
+   elsif cmd == "I" then
+      var byte a, b, c, d
+      a = CANSTAT
+      b = COMSTAT
+      c = RXB0CON
+      d = RXB1CON
+      device = "I"
+      print_byte_hex(device, a)
+      device = 32
+      print_byte_hex(device, b)
+      device = 32
+      print_byte_hex(device, c)
+      device = 32
+      print_byte_hex(device, c)
+      device = 13
+      return 1
+
+      -- CLOSE
+   elsif cmd == "C" then
+      can_adapter_is_open = 0
+      device = 13
+      return 1
+
+   end if
+
+   return 0
+end function
+
+-- these commands are only valid while the bridge is 'closed'
+-- this routine is primarily for internal use.
+function can_closed_cmd(volatile byte out device, byte in ascii_buf[32]) return bit is
+   var byte cmd
+   cmd = ascii_buf[0]
+
+   -- FIXME speed
+   if cmd == "S" then
+      device = 13
+      return 1
+
+      -- FIXME advanced speed
+   elsif cmd == "s" then
+      device = 13
+      return 1
+
+      -- filter/acceptance mask
+      -- m12345678
+   elsif cmd == "m" then
+      var byte sidh, sidl, eidh, eidl
+      sidh = _ascii2bin(ascii_buf[1]) << 4
+      sidh = sidh | _ascii2bin(ascii_buf[2])
+      sidl = _ascii2bin(ascii_buf[3]) << 4
+      sidl = sidl | _ascii2bin(ascii_buf[4])
+      eidh = _ascii2bin(ascii_buf[5]) << 4
+      eidh = eidh | _ascii2bin(ascii_buf[6])
+      eidl = _ascii2bin(ascii_buf[7]) << 4
+      eidl = eidl | _ascii2bin(ascii_buf[8])
+      can_set_rxb0_mask(sidh, sidl, eidh, eidl)
+      device = 13
+      return 1
+
+      -- filter/acceptance code/value
+      -- M12345678
+   elsif cmd == "M" then
+      var byte sidh, sidl, eidh, eidl
+      sidh = _ascii2bin(ascii_buf[1]) << 4
+      sidh = sidh | _ascii2bin(ascii_buf[2])
+      sidl = _ascii2bin(ascii_buf[3]) << 4
+      sidl = sidl | _ascii2bin(ascii_buf[4])
+      eidh = _ascii2bin(ascii_buf[5]) << 4
+      eidh = eidh | _ascii2bin(ascii_buf[6])
+      eidl = _ascii2bin(ascii_buf[7]) << 4
+      eidl = eidl | _ascii2bin(ascii_buf[8])
+      can_set_rxb0_filter0(sidh, sidl, eidh, eidl)
+      device = 13
+      return 1
+
+      -- FIXME timestamp
+   elsif cmd == "Z" then
+      device = 13
+      return 1
+
+      -- OPEN
+   elsif cmd == "O" then
+      can_adapter_is_open = 1
+      device = 13
+      return 1
+
+      -- FIXME: need to really support this.
+      -- LISTEN
+   elsif cmd == "L" then
+      can_adapter_is_open = 1
+      device = 13
+      return 1
+
+      -- BOOT (software reset)
+   elsif cmd == "B" then
+      asm reset
+      -- never gets here
+      return 0
+   end if
+
+   return 0
+end function
+
+-- these commands are only valid while the bridge is 'open'
+-- this routine is primarily for internal use.
+function can_open_cmd(volatile byte out device, byte in ascii_buf[32]) return bit is
+   var byte cmd, data_len
+   var byte can_data[8]
+   var dword can_id
+
+   cmd = ascii_buf[0]
+
+   -- STATUS
+   if cmd == "F" then
+      var byte v
+      v = COMSTAT
+      device = "F"
+      print_byte_hex(device, v)
+      device = 13
+      return 1
+
+      -- bridge CAN message
+   elsif ascii_to_can(ascii_buf, can_id, can_data, data_len) then
+      if defined(display_can_msg) == true then
+         display_can_msg(can_id, can_data, data_len)
+      end if
+      for 100 loop
+         if can_send(0, can_id, can_data, data_len) then
+            exit loop
+         end if
+      end loop
+      -- if can_is_ext_id(can_id) then
+      --    device = "Z"
+      -- else
+      --    device = "z"
+      -- end if
+      device = 13
+      return 1
+   end if
+
+   return 0
+end function
+
+var volatile byte can_ascii_rxbuf[32]
+var volatile byte can_ascii_rxcnt = 0
+
+-- this routine is used to process incoming characters from the UART.
+-- the data stream is line-oriented ASCII, with a CR(13) terminator.
+-- sometimes the data is a command, which may need a reply back out
+-- the UART.  But most of the time, the data is encapsulated CAN messages
+-- which need to be sent out the CANbus.
+--
+--  device: uart data device, e.g. serial_hw_data
+--  ch:  received ASCII char from UART
+procedure can_check_uart_rx(volatile byte out device, byte in ch) is
+   var byte i, data_len
+
+   if can_ascii_rxcnt >= 32 then
+      can_ascii_rxcnt = 0
+      return
+   end if
+
+   can_ascii_rxbuf[can_ascii_rxcnt] = ch
+   can_ascii_rxcnt = can_ascii_rxcnt + 1
+
+   if can_ascii_rxcnt >= 32 then
+      can_ascii_rxcnt = 0
+      return
+   end if
+
+   if ch != 13 then
+      return
+   end if
+
+   -- at this point we have a complete
+   -- ASCII string in the buffer.
+
+   if can_modeless_cmd(device, can_ascii_rxbuf) then
+      can_ascii_rxcnt = 0
+      return
+   end if
+
+   if can_adapter_is_open == 0 then
+      if can_closed_cmd(device, can_ascii_rxbuf) then
+         can_ascii_rxcnt = 0
+         return
+      end if
+   end if
+
+   if can_adapter_is_open then
+      if can_open_cmd(device, can_ascii_rxbuf) then
+         can_ascii_rxcnt = 0
+         return
+      end if
+   end if
+
+   -- discard unknown command
+   can_ascii_rxcnt = 0
+end procedure
+
+-- this routine encapsulates incoming CANbus messages, and sends the resulting ASCII out to the UART.
+-- a copy of the CANbus message is also returned to the caller.
+--
+-- device: uart device, e.g. serial_hw_data
+function can_check_can_rx(volatile byte out device, dword out can_id, byte out can_data[8], byte out data_len) return bit is
+   var bit got_msg
+   var byte i, c
+   var byte ascii_txcnt, ascii_txbuf[32]
+
+   -- always read the CAN msg. this will flush old/stale msgs.
+   got_msg = can_receive(1, can_id, can_data, data_len)
+
+   if (got_msg == 0) then
+      return 0
+   end if
+
+   if can_adapter_is_open then
+      ascii_txcnt = can_to_ascii(can_id, can_data, data_len, ascii_txbuf)
+      for ascii_txcnt using i loop
+         device = ascii_txbuf[i]
+      end loop
+   end if
+
+   return 1
+end function
+

--
You received this message because you are subscribed to the Google Groups 
"jallib" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/jallib?hl=en.

Reply via email to