Revision: 1324 Author: bvwelch Date: Tue Sep 15 12:27:12 2009 Log: revised for socket-CAN support
http://code.google.com/p/jallib/source/detail?r=1324 Modified: /trunk/include/external/can/can_mcp2515.jal ======================================= --- /trunk/include/external/can/can_mcp2515.jal Thu Aug 27 09:58:42 2009 +++ /trunk/include/external/can/can_mcp2515.jal Tue Sep 15 12:27:12 2009 @@ -9,7 +9,7 @@ -- interface. The controller has 3 transmit buffers and 2 receive buffers. -- -- Note: uses SPI Master library and also needs a 'chip select' pin such as: --- var bit can_sel is pin_B0 +-- alias can_sel is pin_B0 -- Three transmit buffers. Each transmit buffer has a control register, header -- registers, length register and (up to ) eight bytes of payload. @@ -246,6 +246,56 @@ const CAN_RX_STATUS_CMD = 0xB0 const CAN_RESET_CMD = 0xC0 +-- the CAN ID uses the same 32-bit unsigned int format as the socket-CAN C library +-- bit 0-28 : CAN identifier (11/29 bit) +-- bit 29 : error frame flag (0 = data frame, 1 = error frame) +-- bit 30 : remote transmission request flag (1 = rtr frame) +-- bit 31 : frame format flag (0 = standard 11 bit, 1 = extended 29 bit) +-- + +procedure can_encode_rtr_id(dword in out can_id) is + pragma inline + var bit rtr at can_id:30 + rtr = 1 +end procedure + +procedure can_encode_ext_id(dword in out can_id) is + pragma inline + var bit ext at can_id:31 + ext = 1 +end procedure + +procedure can_encode_std_id(dword in out can_id) is + pragma inline + var bit ext at can_id:31 + ext = 0 +end procedure + +-- FIXME: will we ever need this? +function can_is_error_id(dword in can_id) return bit is + pragma inline + var bit error at can_id:29 + return error +end function + +function can_is_rtr_id(dword in can_id) return bit is + pragma inline + var bit rtr at can_id:30 + return rtr +end function + +function can_is_ext_id(dword in can_id) return bit is + pragma inline + var bit ext at can_id:31 + return ext +end function + +function can_is_std_id(dword in can_id) return bit is + pragma inline + var bit ext at can_id:31 + return ext == 0 +end function + -- mcp2515 Reset instruction. -- Puts the mcp2515 in Configuration Mode. procedure can_reset() is @@ -373,13 +423,36 @@ can_write(CAN_RXF5EID0, eid0) end procedure --- send standard 11-bit CAN frame +-- send CAN frame -- Non-blocking -- function returns immediately if buffer is busy (in-use) -- FIXME. this is ugly code -function can_send(byte in buf_no, word in std_id, byte in buf[8], byte in len) return bit is - var bit stat - var byte r_base, i - var word sidh, sidl +function can_send(byte in buf_no, dword in can_id, byte in buf[8], byte in len) return bit is + var bit can_id_rtr at can_id:30 + var bit can_id_ext at can_id:31 + var bit stat, rtr, exid + var byte r_base, i, v + var dword sidh, sidl, eidh, eidl, dtmp + + exid = can_id_ext + rtr = can_id_rtr + + -- bullet-proofing + if exid then + can_id = can_id & 0x1FFFFFFF + else + can_id = can_id & 0x7FF + end if + + -- bullet-proofing + if len > 8 then + len = 8 + end if + + -- Remote Request frame? set RTR bit + if rtr then + len = len | 0x40 + end if + if buf_no == 0 then r_base = CAN_TXB0CTRL elsif buf_no == 1 then @@ -400,14 +473,40 @@ can_write(r_base, 0) -- N.B. SIDH and SIDL bit-layout are weird (see datasheet) - sidh = std_id >> 3 - sidl = std_id & 7 - sidl = sidl << 5 + -- tip: to allow both 11-bit and 29-bit on same bus and same controller, + -- the 29-bit is broken into an 11-bit section and an 18-bit section. + + -- we'll do the 18-bit section first + + if exid then + eidl = can_id & 0xff + can_id = can_id >> 8 + + eidh = can_id & 0xff + can_id = can_id >> 8 + + sidl = can_id & 3 + can_id = can_id >> 2 + + -- set the EXIDEN bit + sidl = sidl | 8 + else + sidl = 0 + end if + + -- now the 11-bit section. + dtmp = can_id & 7 + can_id = can_id >> 3 + dtmp = dtmp << 5 + sidl = sidl | dtmp + + -- the final 8 bits. + sidh = can_id can_write(r_base+1, sidh) can_write(r_base+2, sidl) - can_write(r_base+3, 0) - can_write(r_base+4, 0) + can_write(r_base+3, eidh) + can_write(r_base+4, eidl) can_write(r_base+5, len) for 8 using i loop var byte j @@ -420,14 +519,17 @@ return 1 end function --- receive standard 11-bit CAN frame +-- receive CAN frame, sets can_id flag bits as to standard/extended, error, and remote. -- Non-blocking -- function returns immediately if no message is available. --- FIXME. N. B. This routine will automatically discard any extended frames! -- FIXME. this is ugly code -function can_receive(byte in buf_no, word out std_id, byte out buf[8], byte out len) return bit is - var bit rtr, ide, stat, ex - var byte op, i - var byte sidh, sidl +function can_receive(byte in buf_no, dword out can_id, byte out buf[8], byte out len) return bit is + var bit can_id_error at can_id:29 + var bit can_id_rtr at can_id:30 + var bit can_id_ext at can_id:31 + var bit rtr, exid, stat + var byte r_base, i, v, op + var byte sidh, sidl, eidh, eidl + var dword dtmp -- quick check to make sure we have a message waiting if buf_no == 0 then @@ -435,32 +537,27 @@ if stat == 0 then return 0 end if + r_base = CAN_RXB0CTRL + op = CAN_READ_RX0_DATA + elsif buf_no == 1 then stat = can_read_status() & 2 if stat == 0 then return 0 end if + r_base = CAN_RXB1CTRL + op = CAN_READ_RX1_DATA else return 0 -- illegal value for buf_no end if - -- N.B. At this point we have a message. We must read it, - -- even if we decide to discard it later. - if buf_no == 0 then - rtr = can_read(CAN_RXB0CTRL) & 8 - sidh = can_read(CAN_RXB0SIDH) - sidl = can_read(CAN_RXB0SIDL) - len = can_read(CAN_RXB0DLC) - op = CAN_READ_RX0_DATA - - elsif buf_no == 1 then - rtr = can_read(CAN_RXB1CTRL) & 8 - sidh = can_read(CAN_RXB1SIDH) - sidl = can_read(CAN_RXB1SIDL) - len = can_read(CAN_RXB1DLC) - op = CAN_READ_RX1_DATA - - end if + -- N.B. At this point we have a message. + rtr = can_read(r_base) & 8 + sidh = can_read(r_base+1) + sidl = can_read(r_base+2) + eidh = can_read(r_base+3) + eidl = can_read(r_base+4) + len = can_read(r_base+5) -- fast read of the buffer can_sel = 0 @@ -470,23 +567,52 @@ end loop can_sel = 1 - -- Remote Request frames do not include any data - if rtr != 0 then - len = 0 + rtr = len & 0x40 + len = len & 0x0F + + -- bullet-proofing + if len > 8 then + len = 8 end if - -- discard 'extended frames' - -- FIXME - ide = sidl & 8 - if ide != 0 then - return 0 + -- is this an extended frame? save this info for later. + exid = sidl & 8 + + -- form the CAN ID, watch out for weird hardware bits. See datasheet. + -- tip: to allow both 11-bit and 29-bit on same bus and same controller, + -- the 29-bit is broken into an 11-bit section and an 18-bit section. + + -- start of 11-bit section. + -- 8 highest bits + can_id = dword(sidh) + + -- next 3 bits. OK that's 11 bits so far. + -- SIDL has a weird layout. see datasheet. + can_id = can_id << 3 + dtmp = dword(sidl) >> 5 + can_id = can_id | dtmp + + if exid then + + -- start of 18-bit section. + -- 2 bits. + can_id = can_id << 2 + dtmp = dword(sidl) & 3 + can_id = can_id | dtmp + + -- next 8 bits + can_id = can_id << 8 + can_id = can_id | dword(eidh) + + -- final 8 bits. 11+18=29 bits. + can_id = can_id << 8 + can_id = can_id | dword(eidl) + end if - -- form the 11-bit ID. See datasheet. - std_id = word(sidh) - std_id = std_id << 3 - sidl = sidl >> 5 - std_id = std_id | word(sidl) + can_id_ext = exid + can_id_rtr = rtr + can_id_error = 0 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 -~----------~----~----~----~------~----~------~--~---
