Subversion Repositories svn.mios32

Compare Revisions

Ignore whitespace Rev 2645 → Rev 2646

/branches/mcan/include/mios32/mios32_can_midi.h
New file
0,0 → 1,171
// $Id: mios32_can_midi.h 528 2009-05-17 16:45:51Z tk $
/*
* Header file for CAN MIDI functions
*
* ==========================================================================
*
* Copyright (C) 2008 Thorsten Klose (tk@midibox.org)
* Licensed for personal non-commercial use only.
* All other rights reserved.
*
* ==========================================================================
*/
 
#ifndef _MIOS32_CAN_MIDI_H
#define _MIOS32_CAN_MIDI_H
 
/////////////////////////////////////////////////////////////////////////////
// Global definitions
/////////////////////////////////////////////////////////////////////////////
 
// allowed numbers: 1..16
#ifndef MIOS32_CAN_MIDI_NUM_PORTS
#define MIOS32_CAN_MIDI_NUM_PORTS 16
#else
#if MIOS32_CAN_MIDI_NUM_PORTS >16
#define MIOS32_CAN_MIDI_NUM_PORTS 16
#endif
#endif
 
/* - Enhanced mode allowed (send/receive extended message)
if necessary (if needed and requested by an other node).
Note: Message type and cable filter is used in this mode.
- If not precised, MCAN is in Basic Mode(not able to send/receive extended message)
*/
//#define MIOS32_CAN_MIDI_ENHANCED
 
/* Change MCAN verbose level here, default is 0
note: can be changed in terminal
no verbose if not defined
*/
//#define MIOS32_CAN_MIDI_VERBOSE_LEVEL 1
 
/* forces the MCAN Input to work with streamed SYSEX
if not defined:
normal flow is: "packet->package"
-> package using APP_MIDI_NotifySysex (MIOS32_MIDI_SysExCallback_Init)
-> package using APP_MIDI_NotifyPackage
(+)less RAM use (-)_SysExStreamCallback_ not usable, more packaging process
if defined flow becomes: "packet->stream" first then stream->package
-> stream using APP_MCAN_NotifySysexStream (MIOS32_CAN_MIDI_SysExStreamCallback_Init)
-> to normal flow
(+)stream ready, less process (-)16KB RAM is used for Sysex buffering
*/
//#define MIOS32_CAN_MIDI_SYSEX_STREAM_FIRST
 
// by default, equal to the mios32 Device_Id (BSL)
//#define MIOS32_CAN_MIDI_NODE_ID 0
 
// MCAN Common Layer applicaton Code
#define MIOS32_MCAN_APP_CODE 0 // MCAN
 
/* Default application code
*/
#ifndef MIOS32_CAN_MIDI_APP_CODE
#define MIOS32_CAN_MIDI_APP_CODE MIOS32_MCAN_APP_CODE
#endif
 
#define MIOS32_CAN_MIDI_BROADCAST_ID 0xff
#define MIOS32_CAN_MIDI_PORT_ALL 0x02
 
// default node destination is all
#ifndef MIOS32_CAN_MIDI_DEF_DEST_ID
#define MIOS32_CAN_MIDI_DEF_DEST_ID MIOS32_CAN_MIDI_BROADCAST_ID
#endif
// default is vlan 0
#ifndef MIOS32_CAN_MIDI_DEF_VMAN
#define MIOS32_CAN_MIDI_DEF_VMAN 0
#endif
// default destination port is
#ifndef MIOS32_CAN_MIDI_DEF_DEST_PORT
#define MIOS32_CAN_MIDI_DEF_DEST_PORT MIOS32_CAN_MIDI_PORT_ALL
#endif
 
 
/////////////////////////////////////////////////////////////////////////////
// Global Types
/////////////////////////////////////////////////////////////////////////////
 
typedef union {
can_packet_t packet;
struct {
can_ext_id_t id;
can_ctrl_t ctrl;
can_data_t data;
};
} mcan_packet_t;
 
typedef union {
struct {
can_ext_id_t id;
u16 data_l;
};
struct {
u32 ext_id;
u16 ports;
};
struct {
// extended
u32 none:1;
u32 is_request:1;
u32 is_extended:1;
u32 src_node:7;
u32 dst_node:8;
u32 app_type:3;
// standard
u32 cable:4;
u32 type:4;
u32 vman_prio:3;
// ports
u8 src_port;
u8 dst_port;
};
} mcan_header_t;
 
 
/////////////////////////////////////////////////////////////////////////////
// Prototypes
/////////////////////////////////////////////////////////////////////////////
 
extern s32 MIOS32_CAN_MIDI_Init(u32 mode);
 
extern s32 MIOS32_CAN_MIDI_VerboseSet(u8 level);
extern s32 MIOS32_CAN_MIDI_VerboseGet(void);
extern s32 MIOS32_CAN_MIDI_NodeIDSet(u8 node_id);
extern s32 MIOS32_CAN_MIDI_NodeIDGet(void);
extern s32 MIOS32_CAN_MIDI_ModeSet(u8 enabled);
extern s32 MIOS32_CAN_MIDI_ModeGet(void);
 
extern s32 MIOS32_CAN_MIDI_FilterInit(u8 bypass);
 
extern s32 MIOS32_CAN_MIDI_CheckAvailable(u8 cable);
 
extern s32 MIOS32_CAN_MIDI_Periodic_mS(void);
 
extern s32 MIOS32_CAN_MIDI_PacketTransmit_NonBlocking(mcan_packet_t p);
extern s32 MIOS32_CAN_MIDI_PacketTransmit(mcan_packet_t p);
 
extern s32 MIOS32_CAN_MIDI_PacketSend_NonBlocking(mcan_header_t header, mios32_midi_package_t package);
extern s32 MIOS32_CAN_MIDI_PacketSend(mcan_header_t header, mios32_midi_package_t package);
 
extern s32 MIOS32_CAN_MIDI_PackageSend_NonBlocking(mios32_midi_package_t package);
extern s32 MIOS32_CAN_MIDI_PackageSend(mios32_midi_package_t package);
extern s32 MIOS32_CAN_MIDI_SysexRepackSend(mcan_header_t header, mios32_midi_package_t package);
 
extern s32 MIOS32_CAN_MIDI_SysexSend_NonBlocking(mcan_header_t header, u8 *stream, u16 size);
extern s32 MIOS32_CAN_MIDI_SysexSend(mcan_header_t header, u8 *stream, u16 size);
 
extern s32 MIOS32_CAN_MIDI_SysExStreamCallback_Init(s32 (*callback_sysex_stream)(mcan_header_t header, u8* stream, u16 size));
 
extern s32 MIOS32_CAN_MIDI_PackageCallback_Init(s32 (*direct_package_callback)(mcan_header_t header, mios32_midi_package_t package));
 
extern s32 MIOS32_CAN_MIDI_PackageReceive(mios32_midi_package_t *package);
 
extern u32 MIOS32_CAN_MIDI_DefaultHeaderInit(mcan_header_t* header);
/////////////////////////////////////////////////////////////////////////////
// Export global variables
/////////////////////////////////////////////////////////////////////////////
extern u8 mios32_mcan_id;
 
 
#endif /* _MIOS32_CAN_MIDI_H */
Property changes:
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: mcan/include/mios32/mios32_can.h
===================================================================
--- mcan/include/mios32/mios32_can.h (revision 0)
+++ mcan/include/mios32/mios32_can.h (revision 2646)
@@ -0,0 +1,263 @@
+// $Id: mios32_can.h 2403 2016-08-15 17:47:50Z tk $
+/*
+ * Header file for CAN functions
+ *
+ * ==========================================================================
+ *
+ * Copyright (C) 2008 Thorsten Klose (tk@midibox.org)
+ * Licensed for personal non-commercial use only.
+ * All other rights reserved.
+ *
+ * ==========================================================================
+ */
+
+#ifndef _MIOS32_CAN_H
+#define _MIOS32_CAN_H
+
+/////////////////////////////////////////////////////////////////////////////
+// Global definitions
+/////////////////////////////////////////////////////////////////////////////
+
+// number of CAN interfaces (0..2)
+#if defined(MIOS32_BOARD_STM32F4DISCOVERY) || defined(MIOS32_BOARD_MBHP_CORE_STM32F4) || defined(MIOS32_BOARD_MBHP_DIPCOREF4)
+#ifndef MIOS32_CAN_NUM
+#define MIOS32_CAN_NUM 1
+#else
+#if MIOS32_CAN_NUM >1
+#define MIOS32_CAN_NUM 1
+#endif
+#endif
+#else
+#define MIOS32_CAN_NUM 0
+# warning "Unsupported MIOS32_BOARD selected!"
+// because of MIDI Area Network Id arbitration and filtering, only STM32F4 is supported.
+#endif
+
+// Tx buffer size (1..256)
+#ifndef MIOS32_CAN_TX_BUFFER_SIZE
+#define MIOS32_CAN_TX_BUFFER_SIZE 128
+// Should be enough for the 1024 bytes of Sysex buffer
+// Note: One CAN packet transmits 8 bytes maximum.
+// We need 1024/8 = 128 packet buffer.
+#endif
+
+// Rx buffer size (1..256)
+#ifndef MIOS32_CAN_RX_BUFFER_SIZE
+#define MIOS32_CAN_RX_BUFFER_SIZE 128
+#endif
+
+// Interface assignment: 0 = disabled, 1 = MIDI, (2 = MBNET ?), (3 = other ?)
+#ifndef MIOS32_CAN1_ASSIGNMENT
+#define MIOS32_CAN1_ASSIGNMENT 1
+#endif
+
+// Interface assignment: 0 = disabled, 1 = MIDI, (2 = MBNET ?), (3 = other ?)
+#ifndef MIOS32_CAN2_ASSIGNMENT
+#define MIOS32_CAN2_ASSIGNMENT 0
+#endif
+
+// Alternate function pin assignement.
+// 0: CAN2.RX->PB5, CAN2.TX->PB6
+// 1: CAN2.RX->PB12, CAN2.TX->PB13
+#ifndef MIOS32_CAN2_ALTFUNC
+#define MIOS32_CAN2_ALTFUNC 0
+#endif
+
+#define MIOS32_CAN_VERBOSE 1
+
+
+
+/////////////////////////////////////////////////////////////////////////////
+// Global Types
+/////////////////////////////////////////////////////////////////////////////
+
+// CAN Standard 11bits Id(16bis reg), used for 16bits filtering only!
+typedef union {
+ u16 ALL;
+ struct {
+ u16 :3;
+ u16 ide:1;
+ u16 rtr:1;
+ u16 :11;
+ };
+
+} can_std_id_t;
+
+// CAN Extended 29bits Id(32Bits reg), CAN_RIxR/CAN_TIxR
+typedef union {
+ u32 ALL;
+ struct {
+ u16 data[2];
+ };
+ struct {
+ u16 data_l;
+ u16 data_h;
+ };
+ struct {
+ u32 TXRQ:1;
+ u32 RTR:1;
+ u32 IDE:1;
+ u32 :29;
+ };
+ struct {
+ u32 txrq:1;
+ u32 rtr:1;
+ u32 ide:1;
+ u32 :29;
+ };
+ struct {
+ u32 :21;
+ u32 std_id:11;
+ };
+ struct {
+ u32 :1;
+ u32 lpc_ctrl:2; // special field for lpc,
+ u32 ext_id:29;
+ };
+} can_ext_id_t;
+
+// CAN control registers CAN_TDTxR/CAN_RDTxR
+typedef union {
+ u32 ALL;
+ struct {
+ u32 dlc:4;
+ u32 :2;
+ u32 fmi:10;
+ u32 time:16;
+ };
+ struct {
+ u32 DLC:4;
+ u32 :4;
+ u32 tgt:1;
+ u32 :23;
+ };
+} can_ctrl_t;
+
+// CAN data registers CAN_TDLxR/CAN_TDHxR/CAN_RDLxR/CAN_RDHxR
+typedef union {
+ struct {
+ u32 ALL[2];
+ };
+ struct {
+ u32 data_l;
+ u32 data_h;
+ };
+ struct {
+ u16 data[4];
+ };
+ struct {
+ u8 bytes[8];
+ };
+} can_data_t;
+
+// CAN mailboxes packet
+typedef struct can_packet_t {
+ can_ext_id_t id;
+ can_ctrl_t ctrl;
+ can_data_t data;
+} can_packet_t;
+
+// CAN 16bits filter
+typedef struct can_std_filter_t {
+ can_std_id_t filt;
+ can_std_id_t mask;
+} can_std_filter_t;
+
+// CAN 32bits filter
+typedef struct can_ext_filter_t {
+ can_ext_id_t filt;
+ can_ext_id_t mask;
+} can_ext_filter_t;
+
+// CAN bus state
+typedef enum {
+ BUS_OK = 2,
+ WARNING = 1,
+ PASSIVE = 0,
+ BUS_OFF = -1
+} can_bus_stat_t;
+
+// CAN error staus
+typedef union {
+ struct {
+ u32 ALL;
+ };
+// struct {
+// u32 rec:8;
+// u32 tec:8;
+// u32 :9;
+// u32 lec:3;
+// u32 :1;
+// u32 boff:1;
+// u32 epvf:1;
+// u32 ewgf:1;
+// };
+ struct {
+ u32 ewgf:1;
+ u32 epvf:1;
+ u32 boff:1;
+ u32 :1;
+ u32 lec:3;
+ u32 :9;
+ u32 tec:8;
+ u32 rec:8;
+ };
+} can_stat_err_t;
+
+// CAN status report
+typedef struct can_stat_report_t {
+ u32 rx_packets_err;
+ u32 tx_packets_ctr;
+ u32 rx_packets_ctr;
+ u32 rx_buff_err_ctr;
+ u8 rx_last_buff_err;
+ can_bus_stat_t bus_state;
+ can_stat_err_t bus_curr_err;
+ can_stat_err_t bus_last_err;
+} can_stat_report_t;
+
+/////////////////////////////////////////////////////////////////////////////
+// Prototypes
+/////////////////////////////////////////////////////////////////////////////
+
+extern s32 MIOS32_CAN_VerboseSet(u8 level);
+extern s32 MIOS32_CAN_VerboseGet(void);
+extern s32 MIOS32_CAN_Init(u32 mode);
+
+extern s32 MIOS32_CAN_IsAssignedToMIDI(u8 can);
+
+extern s32 MIOS32_CAN_InitPort(u8 can, u8 is_midi);
+extern s32 MIOS32_CAN_InitPortDefault(u8 can);
+extern s32 MIOS32_CAN_InitPeriph(u8 can);
+extern s32 MIOS32_CAN_Init32bitFilter(u8 bank, u8 fifo, can_ext_filter_t filter, u8 enabled);
+extern s32 MIOS32_CAN_Init16bitFilter(u8 bank, u8 fifo, can_std_filter_t filter1, can_std_filter_t filter2, u8 enabled);
+extern s32 MIOS32_CAN_InitPacket(can_packet_t *packet);
+
+extern s32 MIOS32_CAN_RxBufferFree(u8 can);
+extern s32 MIOS32_CAN_RxBufferUsed(u8 can);
+extern s32 MIOS32_CAN_RxBufferGet(u8 can, can_packet_t *p);
+extern s32 MIOS32_CAN_RxBufferPeek(u8 can, can_packet_t *p);
+extern s32 MIOS32_CAN_RxBufferRemove(u8 can);
+extern s32 MIOS32_CAN_RxBufferPut(u8 can, can_packet_t p);
+
+extern s32 MIOS32_CAN_TxBufferFree(u8 can);
+extern s32 MIOS32_CAN_TxBufferUsed(u8 can);
+extern s32 MIOS32_CAN_TxBufferGet(u8 can, can_packet_t *p);
+extern s32 MIOS32_CAN_TxBufferPutMore_NonBlocking(u8 can, can_packet_t* p,u16 len);
+extern s32 MIOS32_CAN_TxBufferPutMore(u8 can, can_packet_t *packets, u16 len);
+extern s32 MIOS32_CAN_TxBufferPut_NonBlocking(u8 can, can_packet_t p);
+extern s32 MIOS32_CAN_TxBufferPut(u8 can, can_packet_t p);
+
+extern s32 MIOS32_CAN_BusErrorCheck(u8 can);
+
+extern s32 MIOS32_CAN_Transmit(u8 can, can_packet_t p, s16 block_time);
+
+extern s32 MIOS32_CAN_ReportLastErr(u8 can, can_stat_err_t* err);
+extern s32 MIOS32_CAN_ReportGetCurr(u8 can, can_stat_report_t* report);
+extern s32 MIOS32_CAN_ReportReset(u8 can);
+/////////////////////////////////////////////////////////////////////////////
+// Export global variables
+/////////////////////////////////////////////////////////////////////////////
+extern u32 can_temp;
+
+#endif /* _MIOS32_CAN_H */
/mcan/include/mios32/mios32_can.h
Property changes:
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: mcan/mios32/STM32F4xx/mios32_can.c
===================================================================
--- mcan/mios32/STM32F4xx/mios32_can.c (revision 0)
+++ mcan/mios32/STM32F4xx/mios32_can.c (revision 2646)
@@ -0,0 +1,1373 @@
+// $Id: mios32_can.c 2312 2016-02-27 23:04:51Z tk $
+//! \defgroup MIOS32_CAN
+//!
+//! U(S)ART functions for MIOS32
+//!
+//! Applications shouldn't call these functions directly, instead please use \ref MIOS32_COM or \ref MIOS32_MIDI layer functions
+//!
+//! \{
+/* ==========================================================================
+ *
+ * Copyright (C) 2008 Thorsten Klose (tk@midibox.org)
+ * Licensed for personal non-commercial use only.
+ * All other rights reserved.
+ *
+ * ==========================================================================
+ */
+
+/////////////////////////////////////////////////////////////////////////////
+// Include files
+/////////////////////////////////////////////////////////////////////////////
+
+#include <mios32.h>
+
+// this module can be optionally enabled in a local mios32_config.h file (included from mios32.h)
+#if defined(MIOS32_USE_CAN)
+
+
+/////////////////////////////////////////////////////////////////////////////
+// Pin definitions and USART mappings
+/////////////////////////////////////////////////////////////////////////////
+
+// how many CANs are supported?
+#define NUM_SUPPORTED_CANS MIOS32_CAN_NUM
+#if MIOS32_CAN_NUM >1
+// Note:If CAN2 is used, J19:SO(PB5) and J4B:SC(PB6)) OR J8/9:SC(PB13) and J8/9:RC1(PB12) are no more available! :-/
+// Defines the start filter bank for the CAN2 interface (Slave) in the range 0 to 27.
+#define MIOS32_CAN2_STARTBANK 14
+#else
+// All filters banks for CAN1
+#define MIOS32_CAN2_STARTBANK 27 // no bank for CAN2
+#endif
+# if defined(MIOS32_BOARD_STM32F4DISCOVERY) || defined(MIOS32_BOARD_MBHP_CORE_STM32F4)
+#define MIOS32_CAN1 CAN1
+#define MIOS32_CAN1_RX_PORT GPIOD
+#define MIOS32_CAN1_RX_PIN GPIO_Pin_0
+#define MIOS32_CAN1_TX_PORT GPIOD
+#define MIOS32_CAN1_TX_PIN GPIO_Pin_1
+#define MIOS32_CAN1_REMAP_FUNC { GPIO_PinAFConfig(GPIOD, GPIO_PinSource0, GPIO_AF_CAN1); GPIO_PinAFConfig(GPIOD, GPIO_PinSource1, GPIO_AF_CAN1); }
+#elif defined(MIOS32_BOARD_MBHP_DIPCOREF4)
+#define MIOS32_CAN1 CAN1
+#define MIOS32_CAN1_RX_PORT GPIOB
+#define MIOS32_CAN1_RX_PIN GPIO_Pin_8
+#define MIOS32_CAN1_TX_PORT GPIOB
+#define MIOS32_CAN1_TX_PIN GPIO_Pin_9
+#define MIOS32_CAN1_REMAP_FUNC { GPIO_PinAFConfig(GPIOB, GPIO_PinSource8, GPIO_AF_CAN1); GPIO_PinAFConfig(GPIOB, GPIO_PinSource9, GPIO_AF_CAN1); }
+#endif
+#define MIOS32_CAN1_RX0_IRQn CAN1_RX0_IRQn
+#define MIOS32_CAN1_RX1_IRQn CAN1_RX1_IRQn
+#define MIOS32_CAN1_TX_IRQn CAN1_TX_IRQn
+#define MIOS32_CAN1_ER_IRQn CAN1_SCE_IRQn
+#define MIOS32_CAN1_RX0_IRQHANDLER_FUNC void CAN1_RX0_IRQHandler(void)
+#define MIOS32_CAN1_RX1_IRQHANDLER_FUNC void CAN1_RX1_IRQHandler(void)
+#define MIOS32_CAN1_TX_IRQHANDLER_FUNC void CAN1_TX_IRQHandler(void)
+#define MIOS32_CAN1_ER_IRQHANDLER_FUNC void CAN1_SCE_IRQHandler(void)
+
+
+#define MIOS32_CAN2 CAN2
+#if MIOS32_CAN2_ALTFUNC == 0 // 0: CAN2.RX->PB5, CAN2.TX->PB6
+#define MIOS32_CAN2_RX_PORT GPIOB
+#define MIOS32_CAN2_RX_PIN GPIO_Pin_5
+#define MIOS32_CAN2_TX_PORT GPIOB
+#define MIOS32_CAN2_TX_PIN GPIO_Pin_6
+#define MIOS32_CAN2_REMAP_FUNC { GPIO_PinAFConfig(GPIOB, GPIO_PinSource5, GPIO_AF_CAN2); GPIO_PinAFConfig(GPIOB, GPIO_PinSource5, GPIO_AF_CAN2); }
+#else // 1: CAN2.RX->PB12, CAN2.TX->PB13
+#define MIOS32_CAN2_RX_PORT GPIOB
+#define MIOS32_CAN2_RX_PIN GPIO_Pin_12
+#define MIOS32_CAN2_TX_PORT GPIOB
+#define MIOS32_CAN2_TX_PIN GPIO_Pin_13
+#define MIOS32_CAN2_REMAP_FUNC { GPIO_PinAFConfig(GPIOB, GPIO_PinSource12, GPIO_AF_CAN2); GPIO_PinAFConfig(GPIOB, GPIO_PinSource13, GPIO_AF_CAN2); }
+#endif
+#define MIOS32_CAN2_RX0_IRQn CAN2_RX0_IRQn
+#define MIOS32_CAN2_RX1_IRQn CAN2_RX1_IRQn
+#define MIOS32_CAN2_TX_IRQn CAN2_TX_IRQn
+#define MIOS32_CAN2_ER_IRQn CAN2_SCE_IRQn
+#define MIOS32_CAN2_RX0_IRQHANDLER_FUNC void CAN2_RX0_IRQHandler(void)
+#define MIOS32_CAN2_RX1_IRQHANDLER_FUNC void CAN2_RX1_IRQHandler(void)
+#define MIOS32_CAN2_TX_IRQHANDLER_FUNC void CAN2_TX_IRQHandler(void)
+#define MIOS32_CAN2_ER_IRQHANDLER_FUNC void CAN2_SCE_IRQHandler(void)
+
+//#define MIOS32_CAN_MIDI_FILT_BK_NODE_SYSEX 0 //Filter Number for Node SysEx
+//#define MIOS32_CAN_MIDI_FILT_BK_SYSEX 1 //Filter Number for Device SysEx
+//
+//#define MIOS32_CAN_MIDI_FILT_BK_NODE_SYSCOM 2 //Filter Number for Node SysCom
+//#define MIOS32_CAN_MIDI_FILT_BK_BYPASS 2 //Filter Number for Node SysCom
+//
+//#define MIOS32_CAN_BANK_FILT_BK_RT 3 //Filter Number for Real time messges
+//#define MIOS32_CAN_MIDI_FILT_BK_SYSCOM 3 //Filter Number for Real time messges
+//
+//#define MIOS32_CAN_MIDI_FILT_BK_NODE_SYSEX 0 //Filter Number for Node SysEx
+//#define MIOS32_CAN_MIDI_FILT_BK_SYSEX 1 //Filter Number for Device SysEx
+
+/////////////////////////////////////////////////////////////////////////////
+// Local variables
+/////////////////////////////////////////////////////////////////////////////
+
+#if NUM_SUPPORTED_CANS >= 1
+static u8 can_assigned_to_midi;
+static can_packet_t rx_buffer[NUM_SUPPORTED_CANS][MIOS32_CAN_RX_BUFFER_SIZE];
+static volatile u16 rx_buffer_tail[NUM_SUPPORTED_CANS];
+static volatile u16 rx_buffer_head[NUM_SUPPORTED_CANS];
+static volatile u16 rx_buffer_size[NUM_SUPPORTED_CANS];
+
+static can_packet_t tx_buffer[NUM_SUPPORTED_CANS][MIOS32_CAN_TX_BUFFER_SIZE];
+static volatile u16 tx_buffer_tail[NUM_SUPPORTED_CANS];
+static volatile u16 tx_buffer_head[NUM_SUPPORTED_CANS];
+static volatile u16 tx_buffer_size[NUM_SUPPORTED_CANS];
+
+static can_stat_report_t can_stat_report[NUM_SUPPORTED_CANS];
+#endif
+
+#if defined MIOS32_CAN_VERBOSE
+static u8 can_verbose = MIOS32_CAN_VERBOSE;
+#else
+static u8 can_verbose = 0;
+#endif
+
+u32 can_temp;
+
+
+
+/////////////////////////////////////////////////////////////////////////////
+//! Initializes CAN MIDI layer
+//! \param[in] mode currently only mode 0 supported
+//! \return < 0 if initialisation failed
+//! \note Applications shouldn't call this function directly, instead please use \ref MIOS32_MIDI layer functions
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_VerboseSet(u8 level)
+{
+#if MIOS32_CAN_NUM == 0
+ return -1; // no CAN enabled
+#else
+
+ can_verbose = level;
+
+ return 0; // no error
+#endif
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+//! Initializes CAN MIDI layer
+//! \param[in] mode currently only mode 0 supported
+//! \return < 0 if initialisation failed
+//! \note Applications shouldn't call this function directly, instead please use \ref MIOS32_MIDI layer functions
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_VerboseGet(void)
+{
+#if MIOS32_CAN_NUM == 0
+ return -1; // no CAN enabled
+#else
+ return can_verbose; // no error
+#endif
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+//! Initializes CAN interfaces
+//! \param[in] mode currently only mode 0 supported
+//! \return < 0 if initialisation failed
+//! \note Applications shouldn't call this function directly, instead please use \ref MIOS32_COM or \ref MIOS32_MIDI layer functions
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_Init(u32 mode)
+{
+ // currently only mode 0 supported
+ if( mode != 0 )
+ return -1; // unsupported mode
+
+#if NUM_SUPPORTED_CANS == 0
+ return -1; // no CANs
+#else
+
+ // map and init CAN pins
+#if MIOS32_CAN1_ASSIGNMENT != 0 // not disabled
+ MIOS32_CAN1_REMAP_FUNC;
+#endif
+#if NUM_SUPPORTED_CANS >= 2 && MIOS32_CAN2_ASSIGNMENT != 0
+ MIOS32_CAN2_REMAP_FUNC;
+#endif
+
+ // enable CANx clocks
+#if MIOS32_CAN1_ASSIGNMENT != 0 // not disabled
+ RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);
+#endif
+#if NUM_SUPPORTED_CANS >= 2 && MIOS32_CAN2_ASSIGNMENT != 0
+ RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN2, ENABLE);
+#endif
+
+ // initialize CANs and clear buffers
+ u8 can;
+ for(can=0; can<NUM_SUPPORTED_CANS; ++can) {
+ // initialize Tx/Rx Buffers
+ rx_buffer_tail[can] = rx_buffer_head[can] = rx_buffer_size[can] = 0;
+ tx_buffer_tail[can] = tx_buffer_head[can] = tx_buffer_size[can] = 0;
+ // initialize info report structure
+ MIOS32_CAN_ReportReset(can);
+ // initialize Default port
+ MIOS32_CAN_InitPortDefault(can);
+ // initialize peripheral
+ if(MIOS32_CAN_InitPeriph(can) < 0)return -1;
+ }
+
+ // configure and enable CAN interrupts
+#if MIOS32_CAN1_ASSIGNMENT != 0 // not disabled
+ // enable CAN interrupt
+ MIOS32_CAN1->IER = 0x0000000;
+ /* Enable MIOS32_CAN1 RX0 interrupt IRQ channel */
+ MIOS32_IRQ_Install(MIOS32_CAN1_RX0_IRQn, MIOS32_IRQ_CAN_PRIORITY);
+ CAN_ITConfig(MIOS32_CAN1, CAN_IT_FMP0, ENABLE);
+ /* Enable MIOS32_CAN1 RX1 interrupt IRQ channel */
+ MIOS32_IRQ_Install(MIOS32_CAN1_RX1_IRQn, MIOS32_IRQ_CAN_PRIORITY);
+ CAN_ITConfig(MIOS32_CAN1, CAN_IT_FMP1, ENABLE);
+ /* Enable MIOS32_CAN1 TX interrupt IRQ channel */
+ MIOS32_IRQ_Install(MIOS32_CAN1_TX_IRQn, MIOS32_IRQ_CAN_PRIORITY);
+ CAN_ITConfig(MIOS32_CAN1, CAN_IT_TME, DISABLE);
+#if 1
+ /* Enable MIOS32_CAN1 SCE(errors) interrupts IRQ channels */
+ MIOS32_IRQ_Install(MIOS32_CAN1_ER_IRQn, MIOS32_IRQ_CAN_PRIORITY);
+ CAN_ITConfig(MIOS32_CAN1, CAN_IT_EWG, ENABLE);
+ CAN_ITConfig(MIOS32_CAN1, CAN_IT_EPV, ENABLE);
+ CAN_ITConfig(MIOS32_CAN1, CAN_IT_BOF, ENABLE);
+ CAN_ITConfig(MIOS32_CAN1, CAN_IT_LEC, DISABLE);
+ CAN_ITConfig(MIOS32_CAN1, CAN_IT_ERR, ENABLE);
+#endif
+#endif
+
+#if NUM_SUPPORTED_CANS >= 2 && MIOS32_CAN1_ASSIGNMENT != 0
+ // enable CAN interrupt
+ MIOS32_CAN2->IER = 0x0000000;
+ /* Enable MIOS32_CAN2 RX0 interrupt IRQ channel */
+ MIOS32_IRQ_Install(MIOS32_CAN2_RX0_IRQn, MIOS32_IRQ_CAN_PRIORITY);
+ CAN_ITConfig(MIOS32_CAN2, CAN_IT_FMP0, ENABLE);
+ /* Enable MIOS32_CAN2 RX1 interrupt IRQ channel */
+ MIOS32_IRQ_Install(MIOS32_CAN2_RX1_IRQn, MIOS32_IRQ_CAN_PRIORITY);
+ CAN_ITConfig(MIOS32_CAN2, CAN_IT_FMP1, ENABLE);
+ /* Enable MIOS32_CAN2 TX interrupt IRQ channel */
+ MIOS32_IRQ_Install(MIOS32_CAN2_TX_IRQn, MIOS32_IRQ_CAN_PRIORITY);
+ CAN_ITConfig(MIOS32_CAN2, CAN_IT_TME, ENABLE);
+#if 0
+ /* Enable MIOS32_CAN2 SCE(errors) interrupts IRQ channels */
+ MIOS32_IRQ_Install(MIOS32_CAN2_ER_IRQn, MIOS32_IRQ_PRIO_MED);
+ CAN_ITConfig(MIOS32_CAN2, CAN_IT_EWG, ENABLE);
+ CAN_ITConfig(MIOS32_CAN2, CAN_IT_EPV, ENABLE);
+ CAN_ITConfig(MIOS32_CAN2, CAN_IT_BOF, ENABLE);
+ CAN_ITConfig(MIOS32_CAN2, CAN_IT_LEC, ENABLE);
+ CAN_ITConfig(MIOS32_CAN2, CAN_IT_ERR, ENABLE);
+#endif
+#endif
+
+ return 0; // no error
+#endif
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+//! \return 0 if CAN is not assigned to a MIDI function
+//! \return 1 if CAN is assigned to a MIDI function
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_IsAssignedToMIDI(u8 can)
+{
+#if NUM_SUPPORTED_CANS == 0
+ return 0; // no CAN available
+#else
+ return (can_assigned_to_midi & (1 << can)) ? 1 : 0;
+#endif
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+//! Initializes a given CAN interface based on given baudrate and TX output mode
+//! \param[in] CAN number (0..1)
+//! \param[in] is_midi MIDI or common CAN interface?
+//! \return < 0 if initialisation failed
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_InitPort(u8 can, u8 is_midi)
+{
+#if NUM_SUPPORTED_CANS == 0
+ return -1; // no CAN available
+#else
+ GPIO_InitTypeDef GPIO_InitStructure;
+ GPIO_StructInit(&GPIO_InitStructure);
+ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
+
+ if( can >= NUM_SUPPORTED_CANS )
+ return -1; // unsupported CAN
+
+ // MIDI assignment
+ if( is_midi ) {
+ can_assigned_to_midi |= (1 << can);
+ } else {
+ can_assigned_to_midi &= ~(1 << can);
+ }
+
+ switch( can ) {
+#if NUM_SUPPORTED_CANS >= 1 && MIOS32_CAN1_ASSIGNMENT != 0
+ case 0: {
+ // configure CAN pins
+ GPIO_InitTypeDef GPIO_InitStructure;
+ GPIO_StructInit(&GPIO_InitStructure);
+ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
+
+ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
+ GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
+ GPIO_InitStructure.GPIO_Pin = MIOS32_CAN1_RX_PIN;
+ GPIO_Init(MIOS32_CAN1_RX_PORT, &GPIO_InitStructure);
+
+ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
+ GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
+ GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
+ GPIO_InitStructure.GPIO_Pin = MIOS32_CAN1_TX_PIN;
+ GPIO_Init(MIOS32_CAN1_TX_PORT, &GPIO_InitStructure);
+ } break;
+#endif
+
+#if NUM_SUPPORTED_CANS >= 2 && MIOS32_CAN2_ASSIGNMENT != 0
+ case 1: {
+ // configure CAN pins
+ GPIO_InitTypeDef GPIO_InitStructure;
+ GPIO_StructInit(&GPIO_InitStructure);
+ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
+
+ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
+ GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
+ GPIO_InitStructure.GPIO_Pin = MIOS32_CAN2_RX_PIN;
+ GPIO_Init(MIOS32_CAN2_RX_PORT, &GPIO_InitStructure);
+
+ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
+ GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
+ GPIO_InitStructure.GPIO_Pin = MIOS32_CAN2_TX_PIN;
+ GPIO_Init(MIOS32_CAN2_TX_PORT, &GPIO_InitStructure);
+ } break;
+#endif
+
+ default:
+ return -1; // unsupported CAN
+ }
+
+ return 0; // no error
+#endif
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+//! Initializes a given CAN interface based on default settings
+//! \param[in] CAN number (0..1)
+//! \return < 0 if initialisation failed
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_InitPortDefault(u8 can)
+{
+#if NUM_SUPPORTED_CANS == 0
+ return -1; // no CAN available
+#else
+ switch( can ) {
+#if NUM_SUPPORTED_CANS >= 1 && MIOS32_CAN1_ASSIGNMENT != 0
+ case 0: {
+ MIOS32_CAN_InitPort(0, MIOS32_CAN1_ASSIGNMENT == 1);
+ } break;
+#endif
+
+#if NUM_SUPPORTED_CANS >= 2 && MIOS32_CAN2_ASSIGNMENT != 0
+ case 1: {
+ MIOS32_CAN_InitPort(1, MIOS32_CAN2_ASSIGNMENT == 1);
+ } break;
+#endif
+
+ default:
+ return -1; // unsupported CAN
+ }
+
+ return 0; // no error
+#endif
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+//! sets the baudrate of a CAN port
+//! \param[in] CAN number (0..1)
+//! \return -1: can not available
+//! \return -2: function not prepared for this CAN
+//! \return -3: CAN Initialisation failed
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_InitPeriph(u8 can)
+{
+#if NUM_SUPPORTED_CANS == 0
+ return -1; // no CAN available
+#else
+ if( can >= NUM_SUPPORTED_CANS )
+ return -1;
+
+ // CAN initialisation
+ CAN_InitTypeDef CAN_InitStruct;
+ CAN_StructInit(&CAN_InitStruct);
+ CAN_InitStruct.CAN_TTCM = DISABLE;
+ CAN_InitStruct.CAN_NART = DISABLE;
+ CAN_InitStruct.CAN_RFLM = ENABLE;
+ CAN_InitStruct.CAN_TXFP = ENABLE;
+ CAN_InitStruct.CAN_ABOM = ENABLE;
+ CAN_InitStruct.CAN_Mode = CAN_Mode_Normal;
+ // -> 84 Mhz / 2 / 3 -> 14 MHz --> 7 quanta for 2 MBaud
+ CAN_InitStruct.CAN_SJW = CAN_SJW_1tq;
+ CAN_InitStruct.CAN_BS1 = CAN_BS1_4tq;
+ CAN_InitStruct.CAN_BS2 = CAN_BS2_2tq;
+ CAN_InitStruct.CAN_Prescaler = 4;
+
+ switch( can ) {
+ case 0: if(CAN_Init(MIOS32_CAN1, &CAN_InitStruct) == CAN_InitStatus_Failed)return -3; break;
+#if NUM_SUPPORTED_CANS >= 2
+ case 1: if(CAN_Init(MIOS32_CAN2, &CAN_InitStruct) == CAN_InitStatus_Failed)return -3; break;
+#endif
+ default:
+ return -2; // not prepared
+ }
+
+ return 0;
+#endif
+}
+
+/////////////////////////////////////////////////////////////////////////////
+//! Initializes a 32 bits filter
+//! \param[in] can filter bank number
+//! \param[in] extended id for filter
+//! \param[in] extended id for mask
+//! \return < 0 if initialisation failed
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_Init32bitFilter(u8 bank, u8 fifo, can_ext_filter_t filter, u8 enabled)
+{
+#if MIOS32_CAN_NUM == 0
+ return -1; // no CAN enabled
+#else
+ CAN_FilterInitTypeDef CAN_FilterInitStructure;
+ // bank / mode / scale
+ CAN_FilterInitStructure.CAN_FilterNumber=bank;
+ CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask;
+ CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit;
+ // filter / mask
+ CAN_FilterInitStructure.CAN_FilterIdHigh=filter.filt.data_h;
+ CAN_FilterInitStructure.CAN_FilterIdLow=filter.filt.data_l;
+ CAN_FilterInitStructure.CAN_FilterMaskIdHigh=filter.mask.data_h;
+ CAN_FilterInitStructure.CAN_FilterMaskIdLow=filter.mask.data_l;
+ // fifo / enable
+ CAN_FilterInitStructure.CAN_FilterFIFOAssignment=0;
+ CAN_FilterInitStructure.CAN_FilterActivation=enabled;
+ CAN_FilterInit(&CAN_FilterInitStructure);
+
+ return 0; // no error
+#endif
+}
+
+/////////////////////////////////////////////////////////////////////////////
+//! Initializes a 16 bits filter
+//! \param[in] can filter bank number
+//! \param[in] standard id for filter
+//! \param[in] standard id for mask
+//! \return < 0 if initialisation failed
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_Init16bitFilter(u8 bank, u8 fifo, can_std_filter_t filter1, can_std_filter_t filter2, u8 enabled)
+{
+#if MIOS32_CAN_NUM == 0
+ return -1; // no CAN enabled
+#else
+ CAN_FilterInitTypeDef CAN_FilterInitStructure;
+ // bank / mode / scale
+ CAN_FilterInitStructure.CAN_FilterNumber=bank;
+ CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask;
+ CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_16bit;
+ // first filter/ firsf mask
+ CAN_FilterInitStructure.CAN_FilterIdLow = filter1.filt.ALL;
+ CAN_FilterInitStructure.CAN_FilterMaskIdLow = filter1.mask.ALL;
+ // second filter / second mask
+ CAN_FilterInitStructure.CAN_FilterIdHigh = filter2.filt.ALL;
+ CAN_FilterInitStructure.CAN_FilterMaskIdHigh = filter2.mask.ALL;
+ // fifo / enable
+ CAN_FilterInitStructure.CAN_FilterFIFOAssignment=fifo;
+ CAN_FilterInitStructure.CAN_FilterActivation=enabled;
+ CAN_FilterInit(&CAN_FilterInitStructure);
+
+ return 0; // no error
+#endif
+}
+
+/////////////////////////////////////////////////////////////////////////////
+//! sets the baudrate of a CAN port
+//! \param[in] CAN number (0..1)
+//! \return -1: can not available
+//! \return -2: function not prepared for this CAN
+//! \return -3: CAN Initialisation failed
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_InitPacket(can_packet_t *packet)
+{
+#if NUM_SUPPORTED_CANS == 0
+ return -1; // no CAN available
+#else
+ // reset
+ packet->id.ALL = 0;
+ packet->ctrl.ALL = 0;
+ packet->data.data_l = 0;
+ packet->data.data_h = 0;
+ return 0;
+#endif
+}
+
+/////////////////////////////////////////////////////////////////////////////
+//! returns number of free bytes in receive buffer
+//! \param[in] CAN number (0..1)
+//! \return can number of free bytes
+//! \return 1: can available
+//! \return 0: can not available
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_RxBufferFree(u8 can)
+{
+#if NUM_SUPPORTED_CANS == 0
+ return 0; // no CAN available
+#else
+ if( can >= NUM_SUPPORTED_CANS )
+ return 0;
+ else
+ return MIOS32_CAN_RX_BUFFER_SIZE - rx_buffer_size[can];
+#endif
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+//! returns number of used bytes in receive buffer
+//! \param[in] CAN number (0..1)
+//! \return > 0: number of used bytes
+//! \return 0 if can not available
+//! \note Applications shouldn't call these functions directly, instead please use \ref MIOS32_COM or \ref MIOS32_MIDI layer functions
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_RxBufferUsed(u8 can)
+{
+#if NUM_SUPPORTED_CANS == 0
+ return 0; // no CAN available
+#else
+ if( can >= NUM_SUPPORTED_CANS )
+ return 0;
+ else
+ return rx_buffer_size[can];
+#endif
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+//! gets a byte from the receive buffer
+//! \param[in] CAN number (0..1)
+//! \return -1 if CAN not available
+//! \return -2 if no new byte available
+//! \return >= 0: number of received bytes
+//! \note Applications shouldn't call these functions directly, instead please use \ref MIOS32_COM or \ref MIOS32_MIDI layer functions
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_RxBufferGet(u8 can, can_packet_t *p)
+{
+#if NUM_SUPPORTED_CANS == 0
+ return -1; // no CAN available
+#else
+ if( can >= NUM_SUPPORTED_CANS )
+ return -1; // CAN not available
+
+ if( !rx_buffer_size[can] )
+ return -2; // nothing new in buffer
+
+ // get byte - this operation should be atomic!
+ MIOS32_IRQ_Disable();
+ *p = rx_buffer[can][rx_buffer_tail[can]];
+ if( ++rx_buffer_tail[can] >= MIOS32_CAN_RX_BUFFER_SIZE )
+ rx_buffer_tail[can] = 0;
+ --rx_buffer_size[can];
+
+ //can_stat_report[can].tx_done_ctr++;
+ MIOS32_IRQ_Enable();
+
+ return 0; // return received byte
+#endif
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+//! returns the next byte of the receive buffer without taking it
+//! \param[in] CAN number (0..1)
+//! \return -1 if CAN not available
+//! \return -2 if no new byte available
+//! \return >= 0: number of received bytes
+//! \note Applications shouldn't call these functions directly, instead please use \ref MIOS32_COM or \ref MIOS32_MIDI layer functions
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_RxBufferPeek(u8 can, can_packet_t *p)
+{
+#if NUM_SUPPORTED_CANS == 0
+ return -1; // no CAN available
+#else
+ if( can >= NUM_SUPPORTED_CANS )
+ return -1; // CAN not available
+
+ if( !rx_buffer_size[can] )
+ return -2; // nothing new in buffer
+
+ // get byte - this operation should be atomic!
+ MIOS32_IRQ_Disable();
+ *p = rx_buffer[can][rx_buffer_tail[can]];
+ MIOS32_IRQ_Enable();
+
+ return 0; // return received byte
+#endif
+}
+
+/////////////////////////////////////////////////////////////////////////////
+//! remove the next byte of the receive buffer without taking it
+//! \param[in] CAN number (0..1)
+//! \return -1 if CAN not available
+//! \return -2 if no new byte available
+//! \return >= 0: number of received bytes
+//! \note Applications shouldn't call these functions directly, instead please use \ref MIOS32_COM or \ref MIOS32_MIDI layer functions
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_RxBufferRemove(u8 can)
+{
+#if NUM_SUPPORTED_CANS == 0
+ return -1; // no CAN available
+#else
+ if( can >= NUM_SUPPORTED_CANS )
+ return -1; // CAN not available
+
+ if( !rx_buffer_size[can] )
+ return -2; // nothing new in buffer
+
+ // dec buffer - this operation should be atomic!
+ MIOS32_IRQ_Disable();
+ if( ++rx_buffer_tail[can] >= MIOS32_CAN_RX_BUFFER_SIZE )
+ rx_buffer_tail[can] = 0;
+ --rx_buffer_size[can];
+ MIOS32_IRQ_Enable();
+
+ return 0; // return received byte
+#endif
+}
+
+/////////////////////////////////////////////////////////////////////////////
+//! puts a byte onto the receive buffer
+//! \param[in] CAN number (0..1)
+//! \param[in] b byte which should be put into Rx buffer
+//! \return 0 if no error
+//! \return -1 if CAN not available
+//! \return -2 if buffer full (retry)
+//! \note Applications shouldn't call these functions directly, instead please use \ref MIOS32_COM or \ref MIOS32_MIDI layer functions
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_RxBufferPut(u8 can, can_packet_t p)
+{
+#if NUM_SUPPORTED_CANS == 0
+ return -1; // no CAN available
+#else
+ if( can >= NUM_SUPPORTED_CANS )
+ return -1; // CAN not available
+
+ if( rx_buffer_size[can] >= MIOS32_CAN_RX_BUFFER_SIZE )
+ return -2; // buffer full (retry)
+
+ // copy received can packet into receive buffer
+ // this operation should be atomic!
+ MIOS32_IRQ_Disable();
+ rx_buffer[can][rx_buffer_head[can]] = p;
+ if( ++rx_buffer_head[can] >= MIOS32_CAN_RX_BUFFER_SIZE )
+ rx_buffer_head[can] = 0;
+ ++rx_buffer_size[can];
+
+
+ MIOS32_IRQ_Enable();
+
+ return 0; // no error
+#endif
+}
+
+/////////////////////////////////////////////////////////////////////////////
+//! returns number of free bytes in transmit buffer
+//! \param[in] CAN number (0..1)
+//! \return number of free bytes
+//! \return 0 if can not available
+//! \note Applications shouldn't call these functions directly, instead please use \ref MIOS32_COM or \ref MIOS32_MIDI layer functions
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_TxBufferFree(u8 can)
+{
+#if NUM_SUPPORTED_CANS == 0
+ return -1; // no CAN available
+#else
+ if( can >= NUM_SUPPORTED_CANS )
+ return -1;
+ else
+ return MIOS32_CAN_TX_BUFFER_SIZE - tx_buffer_size[can];
+#endif
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+//! returns number of used bytes in transmit buffer
+//! \param[in] CAN number (0..1)
+//! \return number of used bytes
+//! \return 0 if can not available
+//! \note Applications shouldn't call these functions directly, instead please use \ref MIOS32_COM or \ref MIOS32_MIDI layer functions
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_TxBufferUsed(u8 can)
+{
+#if NUM_SUPPORTED_CANS == 0
+ return -1; // no CAN available
+#else
+ if( can >= NUM_SUPPORTED_CANS )
+ return -1;
+ else
+ return tx_buffer_size[can];
+#endif
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+//! gets a byte from the transmit buffer
+//! \param[in] CAN number (0..1)
+//! \return -1 if CAN not available
+//! \return -2 if no new byte available
+//! \return >= 0: transmitted byte
+//! \note Applications shouldn't call these functions directly, instead please use \ref MIOS32_COM or \ref MIOS32_MIDI layer functions
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_TxBufferGet(u8 can, can_packet_t *p)
+{
+#if NUM_SUPPORTED_CANS == 0
+ return -1; // no CAN available
+#else
+ if( can >= NUM_SUPPORTED_CANS )
+ return -1; // CAN not available
+
+ if( !tx_buffer_size[can] )
+ return -2; // nothing new in buffer
+
+ // get byte - this operation should be atomic!
+ MIOS32_IRQ_Disable();
+ *p = tx_buffer[can][tx_buffer_tail[can]];
+ if( ++tx_buffer_tail[can] >= MIOS32_CAN_TX_BUFFER_SIZE )
+ tx_buffer_tail[can] = 0;
+ --tx_buffer_size[can];
+ MIOS32_IRQ_Enable();
+
+ return 0; // return transmitted byte
+#endif
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+//! puts more than one byte onto the transmit buffer (used for atomic sends)
+//! \param[in] CAN number (0..1)
+//! \param[in] *buffer pointer to buffer to be sent
+//! \param[in] len number of bytes to be sent
+//! \return 0 if no error
+//! \return -1 if CAN not available
+//! \return -2 if buffer full or cannot get all requested bytes (retry)
+//! \return -3 if CAN not supported by MIOS32_CAN_TxBufferPut Routine
+//! \note Applications shouldn't call these functions directly, instead please use \ref MIOS32_COM or \ref MIOS32_MIDI layer functions
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_TxBufferPutMore_NonBlocking(u8 can, can_packet_t* p,u16 len)
+{
+#if NUM_SUPPORTED_CANS == 0
+ return -1; // no CAN available
+#else
+ if( can >= NUM_SUPPORTED_CANS )
+ return -1; // CAN not available
+
+ if( (tx_buffer_size[can] + len) >= MIOS32_CAN_TX_BUFFER_SIZE )
+ return -2; // buffer full or cannot get all requested bytes (retry)
+
+ // exit immediately if CAN bus errors (CAN doesn't send messages anymore)
+ if( MIOS32_CAN_BusErrorCheck(can) < 0 )
+ return -3; // bus error
+
+ CAN_TypeDef* CANx = NULL;
+ if(!can)CANx = MIOS32_CAN1;else CANx = MIOS32_CAN2;
+ u16 i;
+ for(i=0; i<len; ++i) {
+ // if buffer is empty / interrupt is not enable
+ // we first try to fill some empty mailboxes
+ if(MIOS32_CAN_TxBufferUsed(can) == 0){
+ // is any mailbox empty ?
+ s8 mailbox = -1;
+ if( CANx->TSR & CAN_TSR_TME0)mailbox = 0;
+ else if( CANx->TSR & CAN_TSR_TME1)mailbox = 1;
+ else if( CANx->TSR & CAN_TSR_TME2)mailbox = 2;
+
+ if(mailbox>=0){
+ // yes, we send the packet
+ p[i].id.txrq = 1; //TX Req flag
+ CANx->sTxMailBox[mailbox].TDTR = p[i].ctrl.ALL;
+ CANx->sTxMailBox[mailbox].TDLR = p[i].data.data_l;
+ CANx->sTxMailBox[mailbox].TDHR = p[i].data.data_h;
+ CANx->sTxMailBox[mailbox].TIR = p[i].id.ALL;
+ // for CAN_Report
+ can_stat_report[can].tx_packets_ctr +=1;
+ // packet directly put in mailbox
+ return mailbox; // >= 0 no error
+ }
+ }
+ // there's something in buffer, new packet must be put after
+ // or mailbpx < 0, we put packet in the buffer first
+ // copy bytes to be transmitted into transmit buffer
+ // this operation should be atomic!
+ MIOS32_IRQ_Disable();
+ tx_buffer[can][tx_buffer_head[can]] = p[i];
+ // for CAN_Report
+ can_stat_report[can].tx_packets_ctr +=1;
+ if( ++tx_buffer_head[can] >= MIOS32_CAN_TX_BUFFER_SIZE )
+ tx_buffer_head[can] = 0;
+ tx_buffer_size[can]++;
+
+ // and we start TME interrupt
+ CANx->IER |= CAN_IT_TME;
+
+ MIOS32_IRQ_Enable();
+ }
+
+
+ return 0; // no error
+#endif
+}
+
+/////////////////////////////////////////////////////////////////////////////
+//! puts more than one byte onto the transmit buffer (used for atomic sends)<BR>
+//! (blocking function)
+//! \param[in] CAN number (0..1)
+//! \param[in] *buffer pointer to buffer to be sent
+//! \param[in] len number of bytes to be sent
+//! \return 0 if no error
+//! \return -1 if CAN not available
+//! \return -3 if CAN not supported by MIOS32_CAN_TxBufferPut Routine
+//! \note Applications shouldn't call these functions directly, instead please use \ref MIOS32_COM or \ref MIOS32_MIDI layer functions
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_TxBufferPutMore(u8 can, can_packet_t *packets, u16 len)
+{
+ s32 error;
+
+ while( (error=MIOS32_CAN_TxBufferPutMore_NonBlocking(can, packets, len)) == -2 );
+
+ return error;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+//! puts a byte onto the transmit buffer
+//! \param[in] CAN number (0..1)
+//! \param[in] b byte which should be put into Tx buffer
+//! \return 0 if no error
+//! \return -1 if CAN not available
+//! \return -2 if buffer full (retry)
+//! \return -3 if CAN not supported by MIOS32_CAN_TxBufferPut Routine
+//! \note Applications shouldn't call these functions directly, instead please use \ref MIOS32_COM or \ref MIOS32_MIDI layer functions
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_TxBufferPut_NonBlocking(u8 can, can_packet_t p)
+{
+ // for more comfortable usage...
+ // -> just forward to MIOS32_CAN_TxBufferPutMore
+ return MIOS32_CAN_TxBufferPutMore(can, &p, 1);
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+//! puts a byte onto the transmit buffer<BR>
+//! (blocking function)
+//! \param[in] CAN number (0..1)
+//! \param[in] b byte which should be put into Tx buffer
+//! \return 0 if no error
+//! \return -1 if CAN not available
+//! \return -3 if CAN not supported by MIOS32_CAN_TxBufferPut Routine
+//! \note Applications shouldn't call these functions directly, instead please use \ref MIOS32_COM or \ref MIOS32_MIDI layer functions
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_TxBufferPut(u8 can, can_packet_t p)
+{
+ s32 error;
+
+ while( (error=MIOS32_CAN_TxBufferPutMore(can, &p, 1)) == -2 );
+
+ return error;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+// Used during transmit or receive polling to determine if a bus error has occured
+// (e.g. receiver passive or no nodes connected to bus)
+// In this case, all pending transmissions will be aborted
+// The midian_state.PANIC flag is set to report to the application, that the
+// bus is not ready for transactions (flag accessible via MIDIAN_ErrorStateGet).
+// This flag will be cleared by WaitAck once we got back a message from any slave
+// OUT: returns -1 if bus permanent off (requires re-initialisation)
+// returns -2 if panic state reached
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_BusErrorCheck(u8 can)
+{
+#if NUM_SUPPORTED_CANS == 0
+ return -1; // no CAN available
+#else
+
+ can_stat_err_t err;
+ err = can_stat_report[can].bus_last_err;
+ //if((CANx->ESR &7)!=0){
+ if((err.tec) > (can_stat_report[can].bus_curr_err.tec)){
+ if(can_verbose)MIOS32_MIDI_SendDebugMessage("[MIOS32_CAN_BusErrorCheck] %s %s %s. rec:%d, tec:%d>", err.ewgf? "warning" : "", err.epvf? "passive" : "", err.boff? "off" : "", err.rec, err.tec);
+
+ if(err.ewgf){
+ can_stat_report[can].bus_state = WARNING;
+ }
+
+ if(err.epvf){
+ can_stat_report[can].bus_state = PASSIVE;
+ }
+ if(err.boff){
+ can_stat_report[can].bus_state = BUS_OFF;
+ }
+ can_stat_report[can].bus_curr_err = err;
+ }else {
+ CAN_TypeDef* CANx = NULL;
+ if(!can)CANx = MIOS32_CAN1;else CANx = MIOS32_CAN2;
+ err.ALL = CANx->ESR;
+ if((err.tec) < (can_stat_report[can].bus_curr_err.tec)){
+ if(can_verbose)MIOS32_MIDI_SendDebugMessage("[MIOS32_CAN_BusErrorCheck] %s %s %s. rec:%d, tec:%d<", err.ewgf? "warning" : "", err.epvf? "passive" : "", err.boff? "off" : "", err.rec, err.tec);
+ can_stat_report[can].bus_curr_err = err;
+ can_stat_report[can].bus_last_err = err;
+ }
+ if(!(err.ALL & 7))can_stat_report[can].bus_state = BUS_OK;
+
+ }
+// CAN_TypeDef* CANx = NULL;
+// if(!can)CANx = MIOS32_CAN1;else CANx = MIOS32_CAN2;
+// err = CANx->ESR;
+//
+// if((err.ALL & 7) < (can_stat_report[can].bus_curr_err.ALL & 7)){
+//
+//
+// if(!err.boff){
+// //MIOS32_CAN_InitPeriph(can);
+// can_stat_report[can].bus_state = PASSIVE;
+// if(can_verbose)MIOS32_MIDI_SendDebugMessage("[MIOS32_CAN_BusErrorCheck] CAN is On! :)");
+// }
+// if(!err.epvf){
+// can_stat_report[can].bus_state = WARNING;
+// CAN_ITConfig(MIOS32_CAN1, CAN_IT_BOF, ENABLE);
+// CAN_ITConfig(MIOS32_CAN1, CAN_IT_ERR, ENABLE);
+// if(can_verbose)MIOS32_MIDI_SendDebugMessage("[MIOS32_CAN_BusErrorCheck] Leaves Passive.");
+// }
+// if(!err.ewgf){
+// can_stat_report[can].bus_state = WARNING;
+// CAN_ITConfig(MIOS32_CAN1, CAN_IT_EPV, ENABLE);
+// CAN_ITConfig(MIOS32_CAN1, CAN_IT_BOF, ENABLE);
+// CAN_ITConfig(MIOS32_CAN1, CAN_IT_ERR, ENABLE);
+// if(can_verbose)MIOS32_MIDI_SendDebugMessage("[MIOS32_CAN_BusErrorCheck] Leaves Warning.");
+// }
+//
+// can_stat_report[can].bus_curr_err = err;
+// CAN_ITConfig(MIOS32_CAN1, CAN_IT_EWG, ENABLE);
+// CAN_ITConfig(MIOS32_CAN1, CAN_IT_EPV, ENABLE);
+// CAN_ITConfig(MIOS32_CAN1, CAN_IT_BOF, ENABLE);
+// CAN_ITConfig(MIOS32_CAN1, CAN_IT_ERR, ENABLE);
+// can_stat_report[can].bus_state = BUS_OK;
+// if(can_verbose)MIOS32_MIDI_SendDebugMessage("[MIOS32_CAN_BusErrorCheck] Bus OK.");
+// }
+ //if(err.lec != 0)can_stat_report[can].bus_last_err = err;
+ return (s32)can_stat_report[can].bus_state ;
+#endif
+}
+
+/////////////////////////////////////////////////////////////////////////////
+//! transmit more than one byte
+//! \param[in] CAN number (0..1)
+//! \param[in] *buffer pointer to buffer to be sent
+//! \param[in] len number of bytes to be sent
+//! \return 0 if no error
+//! \return -1 if CAN not available
+//! \return -2 if buffer full or cannot get all requested bytes (retry)
+//! \return -3 if CAN not supported by MIOS32_CAN_TxBufferPut Routine
+//! \note Applications shouldn't call these functions directly, instead please use \ref MIOS32_COM or \ref MIOS32_MIDI layer functions
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_Transmit(u8 can, can_packet_t p, s16 block_time)
+{
+#if NUM_SUPPORTED_CANS == 0
+ return -1; // no CAN available
+#else
+ if( can >= NUM_SUPPORTED_CANS )
+ return -1; // CAN not available
+
+ s8 mailbox = -2;
+ CAN_TypeDef* CANx = NULL;
+
+ //MIOS32_IRQ_Disable();
+
+ if(!can)CANx = MIOS32_CAN1; else CANx = MIOS32_CAN2;
+
+ // exit immediately if CAN bus errors (CAN doesn't send messages anymore)
+ //if( MIOS32_CAN_BusErrorCheck(can) < 0 )
+ //return -3; // bus error
+
+
+ do {
+ if(block_time>=1)block_time--;
+
+ // select an empty transmit mailbox
+ if( CANx->TSR & CAN_TSR_TME0)mailbox = 0;
+ else if( CANx->TSR & CAN_TSR_TME1)mailbox = 1;
+ else if( CANx->TSR & CAN_TSR_TME2)mailbox = 2;
+
+ } while (mailbox == -2 && block_time);
+
+ // exit on busy mailboxes and time out
+ if(mailbox == -2)return -2;
+
+ p.id.txrq = 1;
+ CANx->sTxMailBox[mailbox].TDTR = p.ctrl.ALL;
+ CANx->sTxMailBox[mailbox].TDLR = p.data.data_l;
+ CANx->sTxMailBox[mailbox].TDHR = p.data.data_h;
+ CANx->sTxMailBox[mailbox].TIR = p.id.ALL;
+ // for CAN_Report
+ can_stat_report[can].tx_packets_ctr++;
+
+ //DEBUG_MSG("[MIOS32_CAN_Transmit] mailbox:%d",mailbox);
+
+ return 0; // no error
+#endif
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// Interrupt handler for first CAN
+// always in this order TX, RX0, RX1, don't change it!
+/////////////////////////////////////////////////////////////////////////////
+#if NUM_SUPPORTED_CANS >= 1
+MIOS32_CAN1_TX_IRQHANDLER_FUNC
+{
+ //if( MIOS32_CAN1->IER & CAN_IT_TME ) { // check if TME enabled
+ while(CAN_GetITStatus(MIOS32_CAN1, CAN_IT_TME)){
+ if(MIOS32_CAN_TxBufferUsed(0) >= 1){
+ u8 mailbox = -1;
+ if( MIOS32_CAN1->TSR & CAN_TSR_TME0)mailbox = 0;
+ else if( MIOS32_CAN1->TSR & CAN_TSR_TME1)mailbox = 1;
+ else if( MIOS32_CAN1->TSR & CAN_TSR_TME2)mailbox = 2;
+ can_packet_t p;
+ MIOS32_CAN_TxBufferGet(0, &p);
+ p.id.txrq = 1; //TX Req flag, this reset RQCPx
+ MIOS32_CAN1->sTxMailBox[mailbox].TDTR = p.ctrl.ALL;
+ MIOS32_CAN1->sTxMailBox[mailbox].TDLR = p.data.data_l;
+ MIOS32_CAN1->sTxMailBox[mailbox].TDHR = p.data.data_h;
+ MIOS32_CAN1->sTxMailBox[mailbox].TIR = p.id.ALL;
+ }else{
+ // nothing to send anymore we reset all RQCPx flags
+ MIOS32_CAN1->TSR |= CAN_TSR_RQCP0|CAN_TSR_RQCP1|CAN_TSR_RQCP2;
+ // disable TME interrupt
+ MIOS32_CAN1->IER &=~CAN_IT_TME;
+ }
+ }
+ // I don't knoow why
+ //MIOS32_CAN1->TSR |= (CAN_TSR_RQCP0|CAN_TSR_RQCP1|CAN_TSR_RQCP2);
+}
+MIOS32_CAN1_RX0_IRQHANDLER_FUNC
+{
+
+ while(MIOS32_CAN1->RF0R & CAN_RF0R_FMP0){ // FMP0 contains number of messages
+ // get EID, MSG and DLC
+ can_packet_t p;
+ p.id.ALL = MIOS32_CAN1->sFIFOMailBox[0].RIR;
+ p.ctrl.ALL = MIOS32_CAN1->sFIFOMailBox[0].RDTR;
+ p.data.data_l = MIOS32_CAN1->sFIFOMailBox[0].RDLR;
+ p.data.data_h = MIOS32_CAN1->sFIFOMailBox[0].RDHR;
+ can_stat_report[0].rx_packets_ctr++;
+
+ s32 status = 0;
+// if((status = MIOS32_CAN_IsAssignedToMIDI(0))){
+// switch(p.id.event){
+// case 0x78 ... 0x7f: // Realtime
+// // no data, we forward (event +0x80)
+// status = MIOS32_MIDI_SendByteToRxCallback(MCAN0, 0x80 + p.id.event);
+// break;
+// case 0x80 ... 0xe7: // Channel Voice messages
+// // Source and destination are transmited first. We just foward MIDI event bytes
+// for( i=2; i< p.ctrl.dlc; i++)status = MIOS32_MIDI_SendByteToRxCallback(MCAN0, p.data.bytes[i]);
+// break;
+// case 0xf0: // SysEx messages
+// // Here we forward all data bytes
+// for( i=0; i< p.ctrl.dlc; i++)status = MIOS32_MIDI_SendByteToRxCallback(MCAN0, p.data.bytes[i]);
+// break;
+// case 0xf1 ... 0xf7: // System Common messages
+// // depends on DLC
+// if(!p.ctrl.dlc)status = MIOS32_MIDI_SendByteToRxCallback(MCAN0, p.id.event);
+// else for( i=0; i< p.ctrl.dlc; i++)status = MIOS32_MIDI_SendByteToRxCallback(MCAN0, p.data.bytes[i]);
+// break;
+// case 0xfe: // Node active Sensing ;)
+// // Here we forward all data bytes
+// for( i=0; i< p.ctrl.dlc; i++)status = MIOS32_MIDI_SendByteToRxCallback(MCAN0, p.data.bytes[i]);
+// break;
+// case 0xf8 ... 0xfd: // Node System Exclusive and Common messages
+// // toDo: foward to Node System Receive
+// break;
+// case 0xff: // Node System Exclusive and Common messages
+// // toDo: foward to Node System Receive
+// break;
+// default:
+// break;
+// }
+// }
+// if( status == 0 ){
+ if((status = MIOS32_CAN_RxBufferPut(0, p)) < 0 ){
+ can_stat_report[0].rx_last_buff_err = status;
+ can_stat_report[0].rx_buff_err_ctr = rx_buffer_size[0];
+ }
+// }
+ // release FIFO
+ MIOS32_CAN1->RF0R |= CAN_RF0R_RFOM0; // set RFOM1 flag
+ }
+}
+
+MIOS32_CAN1_RX1_IRQHANDLER_FUNC
+{
+
+ while(MIOS32_CAN1->RF1R & CAN_RF1R_FMP1){ // FMP1 contains number of messages
+ // get EID, MSG and DLC
+ can_packet_t p;
+ p.id.ALL = MIOS32_CAN1->sFIFOMailBox[1].RIR;
+ p.ctrl.ALL = MIOS32_CAN1->sFIFOMailBox[1].RDTR;
+ p.data.data_l = MIOS32_CAN1->sFIFOMailBox[1].RDLR;
+ p.data.data_h = MIOS32_CAN1->sFIFOMailBox[1].RDHR;
+ can_stat_report[0].rx_packets_ctr++;
+
+ s32 status = 0;
+// if((status = MIOS32_CAN_IsAssignedToMIDI(0))){
+// switch(p.id.event){
+// case 0x78 ... 0x7f: // Realtime
+// // no data, we forward (event +0x80)
+// status = MIOS32_MIDI_SendByteToRxCallback(MCAN0, 0x80 + p.id.event);
+// break;
+// case 0x80 ... 0xe7: // Channel Voice messages
+// // Source and destination are transmited first. We just foward MIDI event bytes
+// for( i=2; i< p.ctrl.dlc; i++)status = MIOS32_MIDI_SendByteToRxCallback(MCAN0, p.data.bytes[i]);
+// break;
+// case 0xf0: // SysEx messages
+// // Here we foward all data bytes
+// for( i=0; i< p.ctrl.dlc; i++)status = MIOS32_MIDI_SendByteToRxCallback(MCAN0, p.data.bytes[i]);
+// break;
+// case 0xf1 ... 0xf7: // System Common messages
+// if(!p.ctrl.dlc)status = MIOS32_MIDI_SendByteToRxCallback(MCAN0, p.id.event);
+// else for( i=0; i< p.ctrl.dlc; i++)status = MIOS32_MIDI_SendByteToRxCallback(MCAN0, p.data.bytes[i]);
+// break;
+// case 0xf8 ... 0xff: // Node System Exclusive and Common messages
+// // toDo: foward to Node System Receive
+// break;
+// default:
+// break;
+// }
+// }
+// if( status == 0 ){
+ if((status = MIOS32_CAN_RxBufferPut(0, p)) < 0 ){
+ can_stat_report[0].rx_last_buff_err = status;
+ can_stat_report[0].rx_buff_err_ctr = rx_buffer_size[0];
+ can_stat_report[0].rx_packets_err++;
+ }
+// }
+ // release FIFO
+ MIOS32_CAN1->RF1R |= CAN_RF1R_RFOM1; // set RFOM1 flag
+ }
+}
+
+#if 1 // Here i tried to add a software fifo and using TME interrupt
+MIOS32_CAN1_ER_IRQHANDLER_FUNC
+{
+
+ if( CAN_GetITStatus(MIOS32_CAN1, CAN_IT_ERR) ) { // General Err interrupt is enabled
+
+ if( (can_stat_report[0].bus_last_err.ALL & 7) != (MIOS32_CAN1->ESR & 7) ){
+ //can_stat_err_t err = MIOS32_CAN1->ESR;
+ can_stat_report[0].bus_last_err.ALL = MIOS32_CAN1->ESR;
+ //if(can_verbose)MIOS32_MIDI_SendDebugMessage("0x%0x", can_stat_report[0].bus_last_err.ALL & 7);
+
+ if(can_stat_report[0].bus_last_err.ewgf){
+ //can_stat_report[0].bus_state = WARNING;
+ CAN_ITConfig(MIOS32_CAN1, CAN_IT_EWG, DISABLE);
+ //MIOS32_CAN_BusErrorCheck(0);
+ }
+ if(can_stat_report[0].bus_last_err.epvf){
+ // definively stop the interrupt
+ //can_stat_report[0].bus_state = PASSIVE;
+ //CAN_ITConfig(MIOS32_CAN1, CAN_IT_ERR, DISABLE);
+ CAN_ITConfig(MIOS32_CAN1, CAN_IT_EPV, DISABLE);
+ //MIOS32_CAN_BusErrorCheck(0);
+ }
+ if(can_stat_report[0].bus_last_err.boff){
+ // definively stop the interrupt
+ //can_stat_report[0].bus_state = BUS_OFF;
+ CAN_ITConfig(MIOS32_CAN1, CAN_IT_ERR, DISABLE);
+ CAN_ITConfig(MIOS32_CAN1, CAN_IT_BOF, DISABLE);
+ //MIOS32_CAN_BusErrorCheck(0);
+ }
+ }
+ CAN_ClearITPendingBit(MIOS32_CAN1, CAN_IT_ERR);
+
+ }
+}
+#endif
+
+#endif
+
+
+/////////////////////////////////////////////////////////////////////////////
+// Interrupt handler for second CAN
+/////////////////////////////////////////////////////////////////////////////
+#if NUM_SUPPORTED_CANS >= 2
+#if 0
+MIOS32_CAN2_TX_IRQHANDLER_FUNC
+{
+ //if( MIOS32_CAN1->IER & CAN_IT_TME ) { // check if TME enabled
+ while(CAN_GetITStatus(MIOS32_CAN2, CAN_IT_TME)){
+ if(MIOS32_CAN_TxBufferUsed(1) >= 1){
+ u8 mailbox = -1;
+ if( MIOS32_CAN2->TSR & CAN_TSR_TME0)mailbox = 0;
+ else if( MIOS32_CAN2->TSR & CAN_TSR_TME1)mailbox = 1;
+ else if( MIOS32_CAN2->TSR & CAN_TSR_TME2)mailbox = 2;
+ can_packet_t p;
+ MIOS32_CAN_TxBufferGet(1, &p);
+ p.id.txrq = 1; //TX Req flag, this reset RQCPx
+ MIOS32_CAN2->sTxMailBox[mailbox].TDTR = p.ctrl.ALL;
+ MIOS32_CAN2->sTxMailBox[mailbox].TDLR = p.data.data_l;
+ MIOS32_CAN2->sTxMailBox[mailbox].TDHR = p.data.data_h;
+ MIOS32_CAN2->sTxMailBox[mailbox].TIR = p.id.ALL;
+ }else{
+ // nothing to send anymore we reset all RQCPx flags
+ MIOS32_CAN2->TSR |= CAN_TSR_RQCP0|CAN_TSR_RQCP1|CAN_TSR_RQCP2;
+ // disable TME interrupt
+ MIOS32_CAN2->IER &=~CAN_IT_TME;
+ }
+ }
+ // I don't knoow why
+ MIOS32_CAN2->TSR |= (CAN_TSR_RQCP0|CAN_TSR_RQCP1|CAN_TSR_RQCP2);
+}
+#endif
+MIOS32_CAN2_RX0_IRQHANDLER_FUNC
+{
+ while(MIOS32_CAN2->RF0R & CAN_RF0R_FMP0){ // FMP0 contains number of messages
+ // get EID, MSG and DLC
+ can_packet_t p;
+ p.id.ALL = MIOS32_CAN2->sFIFOMailBox[0].RIR;
+ p.ctrl.ALL = MIOS32_CAN2->sFIFOMailBox[0].RDTR;
+ p.data.data_l = MIOS32_CAN2->sFIFOMailBox[0].RDLR;
+ p.data.data_h = MIOS32_CAN2->sFIFOMailBox[0].RDHR;
+
+ u8 i;
+ s32 status = 0;
+
+ if(MIOS32_CAN_RxBufferPut(1, p) < 0 ){
+ // here we could add some error handling
+ }
+ // release FIFO
+ MIOS32_CAN2->RF0R |= CAN_RF0R_RFOM0; // set RFOM1 flag
+ }
+}
+
+MIOS32_CAN2_RX1_IRQHANDLER_FUNC
+{
+ while(MIOS32_CAN2->RF1R & CAN_RF1R_FMP1 ){ // FMP1 contains number of messages
+ // get EID, MSG and DLC
+ can_packet_t p;
+ p.id.ALL = MIOS32_CAN2->sFIFOMailBox[1].RIR;
+ p.ctrl.ALL = MIOS32_CAN2->sFIFOMailBox[1].RDTR;
+ p.data.data_l = MIOS32_CAN2->sFIFOMailBox[1].RDLR;
+ p.data.data_h = MIOS32_CAN2->sFIFOMailBox[1].RDHR;
+
+ u8 i;
+ s32 status = 0;
+ if((status = MIOS32_CAN_IsAssignedToMIDI(1))){
+ switch(p.id.event){
+ case 0x78 ... 0x7f: // Realtime
+ // no data, we forward (event +0x80)
+ status = MIOS32_MIDI_SendByteToRxCallback(MCAN0+16, 0x80 + p.id.event);
+ break;
+ case 0x80 ... 0xe7: // Channel Voice messages
+ // Source and destination are transmited first. We just foward MIDI event bytes
+ for( i=2; i< p.ctrl.dlc; i++)status = MIOS32_MIDI_SendByteToRxCallback(MCAN0+16, p.data.bytes[i]);
+ break;
+ case 0xf0: // SysEx messages
+ // Here we foward all data bytes
+ for( i=0; i< p.ctrl.dlc; i++)status = MIOS32_MIDI_SendByteToRxCallback(MCAN0+16, p.data.bytes[i]);
+ break;
+ case 0xf1 ... 0xf7: // System Common messages
+ if(!p.ctrl.dlc)status = MIOS32_MIDI_SendByteToRxCallback(MCAN0+16, p.id.event);
+ else for( i=0; i< p.ctrl.dlc; i++)status = MIOS32_MIDI_SendByteToRxCallback(MCAN0+16, p.data.bytes[i]);
+ break;
+ case 0xf8 ... 0xff: // Node System Exclusive and Common messages
+ // toDo: foward to Node System Receive
+ break;
+ default:
+ break;
+ }
+ }
+ if( status == 0 ){
+ if(MIOS32_CAN_RxBufferPut(1, p) < 0 ){
+ // here we could add some error handling
+ }
+ }
+ // release FIFO
+ MIOS32_CAN2->RF1R |= CAN_RF1R_RFOM1; // set RFOM1 flag
+ }
+}
+
+#endif
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_Hlp_ErrorVerbose(CAN_TypeDef* CANx)
+{
+#if NUM_SUPPORTED_CANS == 0
+ return -1; // no CAN available
+#else
+
+
+ return 0; // no error
+#endif
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_ReportLastErr(u8 can, can_stat_err_t* err)
+{
+#if NUM_SUPPORTED_CANS == 0
+ return -1; // no CAN available
+#else
+ *err= can_stat_report[can].bus_last_err;
+ return 0; // no error
+#endif
+}
+
+/////////////////////////////////////////////////////////////////////////////
+//
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_ReportGetCurr(u8 can, can_stat_report_t* report)
+{
+#if NUM_SUPPORTED_CANS == 0
+ return -1; // no CAN available
+#else
+ CAN_TypeDef* CANx = NULL;
+ if(!can)CANx = MIOS32_CAN1;else CANx = MIOS32_CAN2;
+
+ can_stat_report[can].bus_curr_err.ALL = CANx->ESR;
+ *report = can_stat_report[can];
+
+ return 0; // no error
+#endif
+}
+
+/////////////////////////////////////////////////////////////////////////////
+//
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_ReportReset(u8 can)
+{
+#if NUM_SUPPORTED_CANS == 0
+ return -1; // no CAN available
+#else
+
+ can_stat_report[can].tx_packets_ctr = 0;
+ can_stat_report[can].rx_packets_err = 0;
+ can_stat_report[can].rx_last_buff_err = 0;
+ can_stat_report[can].rx_buff_err_ctr = 0;
+ can_stat_report[can].rx_packets_ctr = 0;
+
+ return 0; // no error
+#endif
+}
+
+
+#endif /* MIOS32_USE_CAN */
/mcan/mios32/STM32F4xx/mios32_can.c
Property changes:
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: mcan/mios32/LPC17xx/mios32_can.c
===================================================================
--- mcan/mios32/LPC17xx/mios32_can.c (revision 0)
+++ mcan/mios32/LPC17xx/mios32_can.c (revision 2646)
@@ -0,0 +1,518 @@
+// $Id: mios32_can.c 2312 2016-02-27 23:04:51Z tk $
+//! \defgroup MIOS32_CAN
+//!
+//! U(S)ART functions for MIOS32
+//!
+//! Applications shouldn't call these functions directly, instead please use \ref MIOS32_COM or \ref MIOS32_MIDI layer functions
+//!
+//! \{
+/* ==========================================================================
+ *
+ * Copyright (C) 2008 Thorsten Klose (tk@midibox.org)
+ * Licensed for personal non-commercial use only.
+ * All other rights reserved.
+ *
+ * ==========================================================================
+ */
+
+/////////////////////////////////////////////////////////////////////////////
+// Include files
+/////////////////////////////////////////////////////////////////////////////
+
+#include <mios32.h>
+
+// this module can be optionally enabled in a local mios32_config.h file (included from mios32.h)
+#if defined(MIOS32_USE_CAN)
+
+
+/////////////////////////////////////////////////////////////////////////////
+// Pin definitions and USART mappings
+/////////////////////////////////////////////////////////////////////////////
+
+// how many CANs are supported?
+#define NUM_SUPPORTED_CANS 0
+
+/////////////////////////////////////////////////////////////////////////////
+// Local variables
+/////////////////////////////////////////////////////////////////////////////
+
+
+/////////////////////////////////////////////////////////////////////////////
+//! Initializes CAN MIDI layer
+//! \param[in] mode currently only mode 0 supported
+//! \return < 0 if initialisation failed
+//! \note Applications shouldn't call this function directly, instead please use \ref MIOS32_MIDI layer functions
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_VerboseSet(u8 level)
+{
+#if MIOS32_CAN_NUM == 0
+ return -1; // no CAN enabled
+#else
+ return 0; // no error
+#endif
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+//! Initializes CAN MIDI layer
+//! \param[in] mode currently only mode 0 supported
+//! \return < 0 if initialisation failed
+//! \note Applications shouldn't call this function directly, instead please use \ref MIOS32_MIDI layer functions
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_VerboseGet(void)
+{
+#if MIOS32_CAN_NUM == 0
+ return -1; // no CAN enabled
+#else
+ return 0; // no error
+#endif
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+//! Initializes CAN interfaces
+//! \param[in] mode currently only mode 0 supported
+//! \return < 0 if initialisation failed
+//! \note Applications shouldn't call this function directly, instead please use \ref MIOS32_COM or \ref MIOS32_MIDI layer functions
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_Init(u32 mode)
+{
+ // currently only mode 0 supported
+ if( mode != 0 )
+ return -1; // unsupported mode
+
+#if NUM_SUPPORTED_CANS == 0
+ return -1; // no CANs
+#else
+ return 0; // no error
+#endif
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+//! \return 0 if CAN is not assigned to a MIDI function
+//! \return 1 if CAN is assigned to a MIDI function
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_IsAssignedToMIDI(u8 can)
+{
+#if NUM_SUPPORTED_CANS == 0
+ return 0; // no CAN available
+#else
+ return 0;
+#endif
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+//! Initializes a given CAN interface based on given baudrate and TX output mode
+//! \param[in] CAN number (0..1)
+//! \param[in] is_midi MIDI or common CAN interface?
+//! \return < 0 if initialisation failed
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_InitPort(u8 can, u8 is_midi)
+{
+#if NUM_SUPPORTED_CANS == 0
+ return -1; // no CAN available
+#else
+ return 0; // no error
+#endif
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+//! Initializes a given CAN interface based on default settings
+//! \param[in] CAN number (0..1)
+//! \return < 0 if initialisation failed
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_InitPortDefault(u8 can)
+{
+#if NUM_SUPPORTED_CANS == 0
+ return -1; // no CAN available
+#else
+ return 0; // no error
+#endif
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+//! sets the baudrate of a CAN port
+//! \param[in] CAN number (0..1)
+//! \return -1: can not available
+//! \return -2: function not prepared for this CAN
+//! \return -3: CAN Initialisation failed
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_InitPeriph(u8 can)
+{
+#if NUM_SUPPORTED_CANS == 0
+ return -1; // no CAN available
+#else
+ return 0;
+#endif
+}
+
+/////////////////////////////////////////////////////////////////////////////
+//! Initializes a 32 bits filter
+//! \param[in] can filter bank number
+//! \param[in] extended id for filter
+//! \param[in] extended id for mask
+//! \return < 0 if initialisation failed
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_Init32bitFilter(u8 bank, u8 fifo, can_ext_filter_t filter, u8 enabled)
+{
+#if MIOS32_CAN_NUM == 0
+ return -1; // no CAN enabled
+#else
+ return 0; // no error
+#endif
+}
+
+/////////////////////////////////////////////////////////////////////////////
+//! Initializes a 16 bits filter
+//! \param[in] can filter bank number
+//! \param[in] standard id for filter
+//! \param[in] standard id for mask
+//! \return < 0 if initialisation failed
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_Init16bitFilter(u8 bank, u8 fifo, can_std_filter_t filter1, can_std_filter_t filter2, u8 enabled)
+{
+#if MIOS32_CAN_NUM == 0
+ return -1; // no CAN enabled
+#else
+ return 0; // no error
+#endif
+}
+
+/////////////////////////////////////////////////////////////////////////////
+//! sets the baudrate of a CAN port
+//! \param[in] CAN number (0..1)
+//! \return -1: can not available
+//! \return -2: function not prepared for this CAN
+//! \return -3: CAN Initialisation failed
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_InitPacket(can_packet_t *packet)
+{
+#if NUM_SUPPORTED_CANS == 0
+ return -1; // no CAN available
+#else
+ return 0;
+#endif
+}
+
+/////////////////////////////////////////////////////////////////////////////
+//! returns number of free bytes in receive buffer
+//! \param[in] CAN number (0..1)
+//! \return can number of free bytes
+//! \return 1: can available
+//! \return 0: can not available
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_RxBufferFree(u8 can)
+{
+#if NUM_SUPPORTED_CANS == 0
+ return 0; // no CAN available
+#else
+ return 0;
+#endif
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+//! returns number of used bytes in receive buffer
+//! \param[in] CAN number (0..1)
+//! \return > 0: number of used bytes
+//! \return 0 if can not available
+//! \note Applications shouldn't call these functions directly, instead please use \ref MIOS32_COM or \ref MIOS32_MIDI layer functions
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_RxBufferUsed(u8 can)
+{
+#if NUM_SUPPORTED_CANS == 0
+ return 0; // no CAN available
+#else
+ return 0;
+#endif
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+//! gets a byte from the receive buffer
+//! \param[in] CAN number (0..1)
+//! \return -1 if CAN not available
+//! \return -2 if no new byte available
+//! \return >= 0: number of received bytes
+//! \note Applications shouldn't call these functions directly, instead please use \ref MIOS32_COM or \ref MIOS32_MIDI layer functions
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_RxBufferGet(u8 can, can_packet_t *p)
+{
+#if NUM_SUPPORTED_CANS == 0
+ return -1; // no CAN available
+#else
+ return 0; // return received byte
+#endif
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+//! returns the next byte of the receive buffer without taking it
+//! \param[in] CAN number (0..1)
+//! \return -1 if CAN not available
+//! \return -2 if no new byte available
+//! \return >= 0: number of received bytes
+//! \note Applications shouldn't call these functions directly, instead please use \ref MIOS32_COM or \ref MIOS32_MIDI layer functions
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_RxBufferPeek(u8 can, can_packet_t *p)
+{
+#if NUM_SUPPORTED_CANS == 0
+ return -1; // no CAN available
+#else
+ return 0; // return received byte
+#endif
+}
+
+/////////////////////////////////////////////////////////////////////////////
+//! remove the next byte of the receive buffer without taking it
+//! \param[in] CAN number (0..1)
+//! \return -1 if CAN not available
+//! \return -2 if no new byte available
+//! \return >= 0: number of received bytes
+//! \note Applications shouldn't call these functions directly, instead please use \ref MIOS32_COM or \ref MIOS32_MIDI layer functions
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_RxBufferRemove(u8 can)
+{
+#if NUM_SUPPORTED_CANS == 0
+ return -1; // no CAN available
+#else
+ return 0; // return received byte
+#endif
+}
+
+/////////////////////////////////////////////////////////////////////////////
+//! puts a byte onto the receive buffer
+//! \param[in] CAN number (0..1)
+//! \param[in] b byte which should be put into Rx buffer
+//! \return 0 if no error
+//! \return -1 if CAN not available
+//! \return -2 if buffer full (retry)
+//! \note Applications shouldn't call these functions directly, instead please use \ref MIOS32_COM or \ref MIOS32_MIDI layer functions
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_RxBufferPut(u8 can, can_packet_t p)
+{
+#if NUM_SUPPORTED_CANS == 0
+ return -1; // no CAN available
+#else
+ return 0; // no error
+#endif
+}
+
+/////////////////////////////////////////////////////////////////////////////
+//! returns number of free bytes in transmit buffer
+//! \param[in] CAN number (0..1)
+//! \return number of free bytes
+//! \return 0 if can not available
+//! \note Applications shouldn't call these functions directly, instead please use \ref MIOS32_COM or \ref MIOS32_MIDI layer functions
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_TxBufferFree(u8 can)
+{
+#if NUM_SUPPORTED_CANS == 0
+ return -1; // no CAN available
+#else
+ if( can >= NUM_SUPPORTED_CANS )
+ return -1;
+ else
+ return MIOS32_CAN_TX_BUFFER_SIZE - tx_buffer_size[can];
+#endif
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+//! returns number of used bytes in transmit buffer
+//! \param[in] CAN number (0..1)
+//! \return number of used bytes
+//! \return 0 if can not available
+//! \note Applications shouldn't call these functions directly, instead please use \ref MIOS32_COM or \ref MIOS32_MIDI layer functions
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_TxBufferUsed(u8 can)
+{
+#if NUM_SUPPORTED_CANS == 0
+ return -1; // no CAN available
+#else
+ if( can >= NUM_SUPPORTED_CANS )
+ return -1;
+ else
+ return tx_buffer_size[can];
+#endif
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+//! gets a byte from the transmit buffer
+//! \param[in] CAN number (0..1)
+//! \return -1 if CAN not available
+//! \return -2 if no new byte available
+//! \return >= 0: transmitted byte
+//! \note Applications shouldn't call these functions directly, instead please use \ref MIOS32_COM or \ref MIOS32_MIDI layer functions
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_TxBufferGet(u8 can, can_packet_t *p)
+{
+#if NUM_SUPPORTED_CANS == 0
+ return -1; // no CAN available
+#else
+ return 0; // no error
+#endif
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+//! puts more than one byte onto the transmit buffer (used for atomic sends)
+//! \param[in] CAN number (0..1)
+//! \param[in] *buffer pointer to buffer to be sent
+//! \param[in] len number of bytes to be sent
+//! \return 0 if no error
+//! \return -1 if CAN not available
+//! \return -2 if buffer full or cannot get all requested bytes (retry)
+//! \return -3 if CAN not supported by MIOS32_CAN_TxBufferPut Routine
+//! \note Applications shouldn't call these functions directly, instead please use \ref MIOS32_COM or \ref MIOS32_MIDI layer functions
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_TxBufferPutMore_NonBlocking(u8 can, can_packet_t* p,u16 len)
+{
+#if NUM_SUPPORTED_CANS == 0
+ return -1; // no CAN available
+#else
+ return 0; // no error
+#endif
+}
+
+/////////////////////////////////////////////////////////////////////////////
+//! puts more than one byte onto the transmit buffer (used for atomic sends)<BR>
+//! (blocking function)
+//! \param[in] CAN number (0..1)
+//! \param[in] *buffer pointer to buffer to be sent
+//! \param[in] len number of bytes to be sent
+//! \return 0 if no error
+//! \return -1 if CAN not available
+//! \return -3 if CAN not supported by MIOS32_CAN_TxBufferPut Routine
+//! \note Applications shouldn't call these functions directly, instead please use \ref MIOS32_COM or \ref MIOS32_MIDI layer functions
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_TxBufferPutMore(u8 can, can_packet_t *packets, u16 len)
+{
+ s32 error;
+
+ while( (error=MIOS32_CAN_TxBufferPutMore_NonBlocking(can, packets, len)) == -2 );
+
+ return error;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+//! puts a byte onto the transmit buffer
+//! \param[in] CAN number (0..1)
+//! \param[in] b byte which should be put into Tx buffer
+//! \return 0 if no error
+//! \return -1 if CAN not available
+//! \return -2 if buffer full (retry)
+//! \return -3 if CAN not supported by MIOS32_CAN_TxBufferPut Routine
+//! \note Applications shouldn't call these functions directly, instead please use \ref MIOS32_COM or \ref MIOS32_MIDI layer functions
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_TxBufferPut_NonBlocking(u8 can, can_packet_t p)
+{
+ // for more comfortable usage...
+ // -> just forward to MIOS32_CAN_TxBufferPutMore
+ return MIOS32_CAN_TxBufferPutMore(can, &p, 1);
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+//! puts a byte onto the transmit buffer<BR>
+//! (blocking function)
+//! \param[in] CAN number (0..1)
+//! \param[in] b byte which should be put into Tx buffer
+//! \return 0 if no error
+//! \return -1 if CAN not available
+//! \return -3 if CAN not supported by MIOS32_CAN_TxBufferPut Routine
+//! \note Applications shouldn't call these functions directly, instead please use \ref MIOS32_COM or \ref MIOS32_MIDI layer functions
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_TxBufferPut(u8 can, can_packet_t p)
+{
+ s32 error;
+
+ while( (error=MIOS32_CAN_TxBufferPutMore(can, &p, 1)) == -2 );
+
+ return error;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+// Used during transmit or receive polling to determine if a bus error has occured
+// (e.g. receiver passive or no nodes connected to bus)
+// In this case, all pending transmissions will be aborted
+// The midian_state.PANIC flag is set to report to the application, that the
+// bus is not ready for transactions (flag accessible via MIDIAN_ErrorStateGet).
+// This flag will be cleared by WaitAck once we got back a message from any slave
+// OUT: returns -1 if bus permanent off (requires re-initialisation)
+// returns -2 if panic state reached
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_BusErrorCheck(u8 can)
+{
+#if NUM_SUPPORTED_CANS == 0
+ return -1; // no CAN available
+#else
+ return 0 ;
+#endif
+}
+
+/////////////////////////////////////////////////////////////////////////////
+//! transmit more than one byte
+//! \param[in] CAN number (0..1)
+//! \param[in] *buffer pointer to buffer to be sent
+//! \param[in] len number of bytes to be sent
+//! \return 0 if no error
+//! \return -1 if CAN not available
+//! \return -2 if buffer full or cannot get all requested bytes (retry)
+//! \return -3 if CAN not supported by MIOS32_CAN_TxBufferPut Routine
+//! \note Applications shouldn't call these functions directly, instead please use \ref MIOS32_COM or \ref MIOS32_MIDI layer functions
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_Transmit(u8 can, can_packet_t p, s16 block_time)
+{
+#if NUM_SUPPORTED_CANS == 0
+ return -1; // no CAN available
+#else
+ return 0; // no error
+#endif
+}
+
+/////////////////////////////////////////////////////////////////////////////
+//
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_ReportLastErr(u8 can, can_stat_err_t* err)
+{
+#if NUM_SUPPORTED_CANS == 0
+ return -1; // no CAN available
+#else
+ return 0; // no error
+#endif
+}
+
+/////////////////////////////////////////////////////////////////////////////
+//
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_ReportGetCurr(u8 can, can_stat_report_t* report)
+{
+#if NUM_SUPPORTED_CANS == 0
+ return -1; // no CAN available
+#else
+ return 0; // no error
+#endif
+}
+
+/////////////////////////////////////////////////////////////////////////////
+//
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_ReportReset(u8 can)
+{
+#if NUM_SUPPORTED_CANS == 0
+ return -1; // no CAN available
+#else
+ return 0; // no error
+#endif
+}
+
+
+#endif /* MIOS32_USE_CAN */
/mcan/mios32/LPC17xx/mios32_can.c
Property changes:
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: mcan/mios32/STM32F10x/mios32_can.c
===================================================================
--- mcan/mios32/STM32F10x/mios32_can.c (revision 0)
+++ mcan/mios32/STM32F10x/mios32_can.c (revision 2646)
@@ -0,0 +1,518 @@
+// $Id: mios32_can.c 2312 2016-02-27 23:04:51Z tk $
+//! \defgroup MIOS32_CAN
+//!
+//! U(S)ART functions for MIOS32
+//!
+//! Applications shouldn't call these functions directly, instead please use \ref MIOS32_COM or \ref MIOS32_MIDI layer functions
+//!
+//! \{
+/* ==========================================================================
+ *
+ * Copyright (C) 2008 Thorsten Klose (tk@midibox.org)
+ * Licensed for personal non-commercial use only.
+ * All other rights reserved.
+ *
+ * ==========================================================================
+ */
+
+/////////////////////////////////////////////////////////////////////////////
+// Include files
+/////////////////////////////////////////////////////////////////////////////
+
+#include <mios32.h>
+
+// this module can be optionally enabled in a local mios32_config.h file (included from mios32.h)
+#if defined(MIOS32_USE_CAN)
+
+
+/////////////////////////////////////////////////////////////////////////////
+// Pin definitions and USART mappings
+/////////////////////////////////////////////////////////////////////////////
+
+// how many CANs are supported?
+#define NUM_SUPPORTED_CANS 0
+
+/////////////////////////////////////////////////////////////////////////////
+// Local variables
+/////////////////////////////////////////////////////////////////////////////
+
+
+/////////////////////////////////////////////////////////////////////////////
+//! Initializes CAN MIDI layer
+//! \param[in] mode currently only mode 0 supported
+//! \return < 0 if initialisation failed
+//! \note Applications shouldn't call this function directly, instead please use \ref MIOS32_MIDI layer functions
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_VerboseSet(u8 level)
+{
+#if MIOS32_CAN_NUM == 0
+ return -1; // no CAN enabled
+#else
+ return 0; // no error
+#endif
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+//! Initializes CAN MIDI layer
+//! \param[in] mode currently only mode 0 supported
+//! \return < 0 if initialisation failed
+//! \note Applications shouldn't call this function directly, instead please use \ref MIOS32_MIDI layer functions
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_VerboseGet(void)
+{
+#if MIOS32_CAN_NUM == 0
+ return -1; // no CAN enabled
+#else
+ return 0; // no error
+#endif
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+//! Initializes CAN interfaces
+//! \param[in] mode currently only mode 0 supported
+//! \return < 0 if initialisation failed
+//! \note Applications shouldn't call this function directly, instead please use \ref MIOS32_COM or \ref MIOS32_MIDI layer functions
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_Init(u32 mode)
+{
+ // currently only mode 0 supported
+ if( mode != 0 )
+ return -1; // unsupported mode
+
+#if NUM_SUPPORTED_CANS == 0
+ return -1; // no CANs
+#else
+ return 0; // no error
+#endif
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+//! \return 0 if CAN is not assigned to a MIDI function
+//! \return 1 if CAN is assigned to a MIDI function
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_IsAssignedToMIDI(u8 can)
+{
+#if NUM_SUPPORTED_CANS == 0
+ return 0; // no CAN available
+#else
+ return 0;
+#endif
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+//! Initializes a given CAN interface based on given baudrate and TX output mode
+//! \param[in] CAN number (0..1)
+//! \param[in] is_midi MIDI or common CAN interface?
+//! \return < 0 if initialisation failed
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_InitPort(u8 can, u8 is_midi)
+{
+#if NUM_SUPPORTED_CANS == 0
+ return -1; // no CAN available
+#else
+ return 0; // no error
+#endif
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+//! Initializes a given CAN interface based on default settings
+//! \param[in] CAN number (0..1)
+//! \return < 0 if initialisation failed
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_InitPortDefault(u8 can)
+{
+#if NUM_SUPPORTED_CANS == 0
+ return -1; // no CAN available
+#else
+ return 0; // no error
+#endif
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+//! sets the baudrate of a CAN port
+//! \param[in] CAN number (0..1)
+//! \return -1: can not available
+//! \return -2: function not prepared for this CAN
+//! \return -3: CAN Initialisation failed
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_InitPeriph(u8 can)
+{
+#if NUM_SUPPORTED_CANS == 0
+ return -1; // no CAN available
+#else
+ return 0;
+#endif
+}
+
+/////////////////////////////////////////////////////////////////////////////
+//! Initializes a 32 bits filter
+//! \param[in] can filter bank number
+//! \param[in] extended id for filter
+//! \param[in] extended id for mask
+//! \return < 0 if initialisation failed
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_Init32bitFilter(u8 bank, u8 fifo, can_ext_filter_t filter, u8 enabled)
+{
+#if MIOS32_CAN_NUM == 0
+ return -1; // no CAN enabled
+#else
+ return 0; // no error
+#endif
+}
+
+/////////////////////////////////////////////////////////////////////////////
+//! Initializes a 16 bits filter
+//! \param[in] can filter bank number
+//! \param[in] standard id for filter
+//! \param[in] standard id for mask
+//! \return < 0 if initialisation failed
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_Init16bitFilter(u8 bank, u8 fifo, can_std_filter_t filter1, can_std_filter_t filter2, u8 enabled)
+{
+#if MIOS32_CAN_NUM == 0
+ return -1; // no CAN enabled
+#else
+ return 0; // no error
+#endif
+}
+
+/////////////////////////////////////////////////////////////////////////////
+//! sets the baudrate of a CAN port
+//! \param[in] CAN number (0..1)
+//! \return -1: can not available
+//! \return -2: function not prepared for this CAN
+//! \return -3: CAN Initialisation failed
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_InitPacket(can_packet_t *packet)
+{
+#if NUM_SUPPORTED_CANS == 0
+ return -1; // no CAN available
+#else
+ return 0;
+#endif
+}
+
+/////////////////////////////////////////////////////////////////////////////
+//! returns number of free bytes in receive buffer
+//! \param[in] CAN number (0..1)
+//! \return can number of free bytes
+//! \return 1: can available
+//! \return 0: can not available
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_RxBufferFree(u8 can)
+{
+#if NUM_SUPPORTED_CANS == 0
+ return 0; // no CAN available
+#else
+ return 0;
+#endif
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+//! returns number of used bytes in receive buffer
+//! \param[in] CAN number (0..1)
+//! \return > 0: number of used bytes
+//! \return 0 if can not available
+//! \note Applications shouldn't call these functions directly, instead please use \ref MIOS32_COM or \ref MIOS32_MIDI layer functions
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_RxBufferUsed(u8 can)
+{
+#if NUM_SUPPORTED_CANS == 0
+ return 0; // no CAN available
+#else
+ return 0;
+#endif
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+//! gets a byte from the receive buffer
+//! \param[in] CAN number (0..1)
+//! \return -1 if CAN not available
+//! \return -2 if no new byte available
+//! \return >= 0: number of received bytes
+//! \note Applications shouldn't call these functions directly, instead please use \ref MIOS32_COM or \ref MIOS32_MIDI layer functions
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_RxBufferGet(u8 can, can_packet_t *p)
+{
+#if NUM_SUPPORTED_CANS == 0
+ return -1; // no CAN available
+#else
+ return 0; // return received byte
+#endif
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+//! returns the next byte of the receive buffer without taking it
+//! \param[in] CAN number (0..1)
+//! \return -1 if CAN not available
+//! \return -2 if no new byte available
+//! \return >= 0: number of received bytes
+//! \note Applications shouldn't call these functions directly, instead please use \ref MIOS32_COM or \ref MIOS32_MIDI layer functions
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_RxBufferPeek(u8 can, can_packet_t *p)
+{
+#if NUM_SUPPORTED_CANS == 0
+ return -1; // no CAN available
+#else
+ return 0; // return received byte
+#endif
+}
+
+/////////////////////////////////////////////////////////////////////////////
+//! remove the next byte of the receive buffer without taking it
+//! \param[in] CAN number (0..1)
+//! \return -1 if CAN not available
+//! \return -2 if no new byte available
+//! \return >= 0: number of received bytes
+//! \note Applications shouldn't call these functions directly, instead please use \ref MIOS32_COM or \ref MIOS32_MIDI layer functions
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_RxBufferRemove(u8 can)
+{
+#if NUM_SUPPORTED_CANS == 0
+ return -1; // no CAN available
+#else
+ return 0; // return received byte
+#endif
+}
+
+/////////////////////////////////////////////////////////////////////////////
+//! puts a byte onto the receive buffer
+//! \param[in] CAN number (0..1)
+//! \param[in] b byte which should be put into Rx buffer
+//! \return 0 if no error
+//! \return -1 if CAN not available
+//! \return -2 if buffer full (retry)
+//! \note Applications shouldn't call these functions directly, instead please use \ref MIOS32_COM or \ref MIOS32_MIDI layer functions
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_RxBufferPut(u8 can, can_packet_t p)
+{
+#if NUM_SUPPORTED_CANS == 0
+ return -1; // no CAN available
+#else
+ return 0; // no error
+#endif
+}
+
+/////////////////////////////////////////////////////////////////////////////
+//! returns number of free bytes in transmit buffer
+//! \param[in] CAN number (0..1)
+//! \return number of free bytes
+//! \return 0 if can not available
+//! \note Applications shouldn't call these functions directly, instead please use \ref MIOS32_COM or \ref MIOS32_MIDI layer functions
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_TxBufferFree(u8 can)
+{
+#if NUM_SUPPORTED_CANS == 0
+ return -1; // no CAN available
+#else
+ if( can >= NUM_SUPPORTED_CANS )
+ return -1;
+ else
+ return MIOS32_CAN_TX_BUFFER_SIZE - tx_buffer_size[can];
+#endif
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+//! returns number of used bytes in transmit buffer
+//! \param[in] CAN number (0..1)
+//! \return number of used bytes
+//! \return 0 if can not available
+//! \note Applications shouldn't call these functions directly, instead please use \ref MIOS32_COM or \ref MIOS32_MIDI layer functions
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_TxBufferUsed(u8 can)
+{
+#if NUM_SUPPORTED_CANS == 0
+ return -1; // no CAN available
+#else
+ if( can >= NUM_SUPPORTED_CANS )
+ return -1;
+ else
+ return tx_buffer_size[can];
+#endif
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+//! gets a byte from the transmit buffer
+//! \param[in] CAN number (0..1)
+//! \return -1 if CAN not available
+//! \return -2 if no new byte available
+//! \return >= 0: transmitted byte
+//! \note Applications shouldn't call these functions directly, instead please use \ref MIOS32_COM or \ref MIOS32_MIDI layer functions
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_TxBufferGet(u8 can, can_packet_t *p)
+{
+#if NUM_SUPPORTED_CANS == 0
+ return -1; // no CAN available
+#else
+ return 0; // no error
+#endif
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+//! puts more than one byte onto the transmit buffer (used for atomic sends)
+//! \param[in] CAN number (0..1)
+//! \param[in] *buffer pointer to buffer to be sent
+//! \param[in] len number of bytes to be sent
+//! \return 0 if no error
+//! \return -1 if CAN not available
+//! \return -2 if buffer full or cannot get all requested bytes (retry)
+//! \return -3 if CAN not supported by MIOS32_CAN_TxBufferPut Routine
+//! \note Applications shouldn't call these functions directly, instead please use \ref MIOS32_COM or \ref MIOS32_MIDI layer functions
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_TxBufferPutMore_NonBlocking(u8 can, can_packet_t* p,u16 len)
+{
+#if NUM_SUPPORTED_CANS == 0
+ return -1; // no CAN available
+#else
+ return 0; // no error
+#endif
+}
+
+/////////////////////////////////////////////////////////////////////////////
+//! puts more than one byte onto the transmit buffer (used for atomic sends)<BR>
+//! (blocking function)
+//! \param[in] CAN number (0..1)
+//! \param[in] *buffer pointer to buffer to be sent
+//! \param[in] len number of bytes to be sent
+//! \return 0 if no error
+//! \return -1 if CAN not available
+//! \return -3 if CAN not supported by MIOS32_CAN_TxBufferPut Routine
+//! \note Applications shouldn't call these functions directly, instead please use \ref MIOS32_COM or \ref MIOS32_MIDI layer functions
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_TxBufferPutMore(u8 can, can_packet_t *packets, u16 len)
+{
+ s32 error;
+
+ while( (error=MIOS32_CAN_TxBufferPutMore_NonBlocking(can, packets, len)) == -2 );
+
+ return error;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+//! puts a byte onto the transmit buffer
+//! \param[in] CAN number (0..1)
+//! \param[in] b byte which should be put into Tx buffer
+//! \return 0 if no error
+//! \return -1 if CAN not available
+//! \return -2 if buffer full (retry)
+//! \return -3 if CAN not supported by MIOS32_CAN_TxBufferPut Routine
+//! \note Applications shouldn't call these functions directly, instead please use \ref MIOS32_COM or \ref MIOS32_MIDI layer functions
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_TxBufferPut_NonBlocking(u8 can, can_packet_t p)
+{
+ // for more comfortable usage...
+ // -> just forward to MIOS32_CAN_TxBufferPutMore
+ return MIOS32_CAN_TxBufferPutMore(can, &p, 1);
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+//! puts a byte onto the transmit buffer<BR>
+//! (blocking function)
+//! \param[in] CAN number (0..1)
+//! \param[in] b byte which should be put into Tx buffer
+//! \return 0 if no error
+//! \return -1 if CAN not available
+//! \return -3 if CAN not supported by MIOS32_CAN_TxBufferPut Routine
+//! \note Applications shouldn't call these functions directly, instead please use \ref MIOS32_COM or \ref MIOS32_MIDI layer functions
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_TxBufferPut(u8 can, can_packet_t p)
+{
+ s32 error;
+
+ while( (error=MIOS32_CAN_TxBufferPutMore(can, &p, 1)) == -2 );
+
+ return error;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+// Used during transmit or receive polling to determine if a bus error has occured
+// (e.g. receiver passive or no nodes connected to bus)
+// In this case, all pending transmissions will be aborted
+// The midian_state.PANIC flag is set to report to the application, that the
+// bus is not ready for transactions (flag accessible via MIDIAN_ErrorStateGet).
+// This flag will be cleared by WaitAck once we got back a message from any slave
+// OUT: returns -1 if bus permanent off (requires re-initialisation)
+// returns -2 if panic state reached
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_BusErrorCheck(u8 can)
+{
+#if NUM_SUPPORTED_CANS == 0
+ return -1; // no CAN available
+#else
+ return 0 ;
+#endif
+}
+
+/////////////////////////////////////////////////////////////////////////////
+//! transmit more than one byte
+//! \param[in] CAN number (0..1)
+//! \param[in] *buffer pointer to buffer to be sent
+//! \param[in] len number of bytes to be sent
+//! \return 0 if no error
+//! \return -1 if CAN not available
+//! \return -2 if buffer full or cannot get all requested bytes (retry)
+//! \return -3 if CAN not supported by MIOS32_CAN_TxBufferPut Routine
+//! \note Applications shouldn't call these functions directly, instead please use \ref MIOS32_COM or \ref MIOS32_MIDI layer functions
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_Transmit(u8 can, can_packet_t p, s16 block_time)
+{
+#if NUM_SUPPORTED_CANS == 0
+ return -1; // no CAN available
+#else
+ return 0; // no error
+#endif
+}
+
+/////////////////////////////////////////////////////////////////////////////
+//
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_ReportLastErr(u8 can, can_stat_err_t* err)
+{
+#if NUM_SUPPORTED_CANS == 0
+ return -1; // no CAN available
+#else
+ return 0; // no error
+#endif
+}
+
+/////////////////////////////////////////////////////////////////////////////
+//
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_ReportGetCurr(u8 can, can_stat_report_t* report)
+{
+#if NUM_SUPPORTED_CANS == 0
+ return -1; // no CAN available
+#else
+ return 0; // no error
+#endif
+}
+
+/////////////////////////////////////////////////////////////////////////////
+//
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_ReportReset(u8 can)
+{
+#if NUM_SUPPORTED_CANS == 0
+ return -1; // no CAN available
+#else
+ return 0; // no error
+#endif
+}
+
+
+#endif /* MIOS32_USE_CAN */
/mcan/mios32/STM32F10x/mios32_can.c
Property changes:
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: mcan/mios32/common/mios32_can_midi.c
===================================================================
--- mcan/mios32/common/mios32_can_midi.c (revision 0)
+++ mcan/mios32/common/mios32_can_midi.c (revision 2646)
@@ -0,0 +1,1252 @@
+// $Id: mios32_uart_midi.c 2312 2016-02-27 23:04:51Z tk $
+//! \defgroup MIOS32_CAN_MIDI
+//!
+//! CAN MIDI layer for MIOS32
+//!
+//! Applications shouldn't call these functions directly, instead please use \ref MIOS32_MIDI layer functions
+//!
+//! \{
+/* ==========================================================================
+ *
+ * Copyright (C) 2008 Thorsten Klose (tk@midibox.org)
+ * Licensed for personal non-commercial use only.
+ * All other rights reserved.
+ *
+ * ==========================================================================
+ */
+
+/////////////////////////////////////////////////////////////////////////////
+// Include files
+/////////////////////////////////////////////////////////////////////////////
+
+#include <mios32.h>
+#include <stdlib.h>
+#include <string.h>
+
+// this module can be optionally disabled in a local mios32_config.h file (included from mios32.h)
+#if defined(MIOS32_USE_CAN_MIDI)
+
+#define MIOS32_CAN_MIDI_ID_MASK 0xe1fffffc
+/////////////////////////////////////////////////////////////////////////////
+// Global variables
+/////////////////////////////////////////////////////////////////////////////
+
+
+#define DEBUG_CAN_LVL1 {if(can_midi_verbose)MIOS32_MIDI_SendDebugMessage}
+#define DEBUG_CAN_LVL2 {if(can_midi_verbose>=2)MIOS32_MIDI_SendDebugMessage}
+#define DEBUG_CAN_LVL3 {if(can_midi_verbose>=3)MIOS32_MIDI_SendDebugMessage}
+/////////////////////////////////////////////////////////////////////////////
+// Local Types
+/////////////////////////////////////////////////////////////////////////////
+
+typedef union {
+ u8 stat;
+ struct {
+ u8 waiting:1;
+ u8 ready:1;
+ u8 ending:1;
+ u8 :5;
+ };
+} sysex_stat_rec_t;
+
+typedef struct sysex_unpack_rec_t{
+ sysex_stat_rec_t stat;
+ u32 ext_id;
+ u32 ports;
+#if defined(MIOS32_CAN_MIDI_SYSEX_STREAM_FIRST)
+ u8 buffer[1024];
+#else
+ u8 buffer[11];
+#endif
+ u16 ctr;
+ u16 timeout_ctr;
+} sysex_unpack_rec_t;
+
+typedef struct sysex_repack_rec_t{
+ sysex_stat_rec_t stat;
+ u32 ext_id;
+ u32 data_l;
+ u8 buffer[10];
+ u8 ctr;
+ u16 packet;
+ u16 timeout_ctr;
+} sysex_repack_rec_t;
+
+
+#if MIOS32_CAN_NUM
+/////////////////////////////////////////////////////////////////////////////
+// Global variables
+/////////////////////////////////////////////////////////////////////////////
+
+// CAN MIDI Node Id
+#if defined MIOS32_CAN_MIDI_NODE_ID
+u8 mios32_mcan_id = MIOS32_CAN_MIDI_NODE_ID;
+#else
+// if not precised it becomes Device_Id on init but can be changed by SW.
+u8 mios32_mcan_id;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// Local variables
+/////////////////////////////////////////////////////////////////////////////
+
+static u8 mios32_mcan_enhanced = 0;
+
+// status structure for sysex record
+static sysex_unpack_rec_t sysex_unpack[MIOS32_CAN_MIDI_NUM_PORTS];
+
+// SysEx repack data structure
+static sysex_repack_rec_t sysex_repack[MIOS32_CAN_MIDI_NUM_PORTS];
+
+// active sense delay counter
+s16 node_active_sense_ctr;
+// for frame rate calculation
+static u32 frame_rate;
+static u32 can_last_baudrate;
+
+// callback for direct sysex stream
+static s32 (*sysex_stream_callback_func)(mcan_header_t header, u8* stream, u16 size);
+static s32 (*direct_package_callback_func)(mcan_header_t header, mios32_midi_package_t package);
+
+// verbose
+static u8 can_midi_verbose = 2;
+
+#endif
+
+
+/////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////
+
+// internal function to reset the record structure
+static s32 MIOS32_CAN_MIDI_SysexUnpackReset(sysex_unpack_rec_t* sysex_unpack)
+{
+#if MIOS32_CAN_NUM > 0
+
+ memset(sysex_unpack, 0, sizeof (struct sysex_unpack_rec_t));
+
+#endif
+ return 0; // no error
+}
+
+/////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////
+
+// internal function to reset the record structure
+static s32 MIOS32_CAN_MIDI_SysexRepackReset(sysex_repack_rec_t* sysex_repack)
+{
+#if MIOS32_CAN_NUM > 0
+
+ memset(sysex_repack, 0, sizeof (struct sysex_repack_rec_t));
+
+#endif
+ return 0; // no error
+}
+/////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////
+
+// internal function to parse configuration commands
+static s32 MIOS32_CAN_MIDI_LocalCmdParser(mcan_header_t header, mios32_midi_package_t* package)
+{
+#if MIOS32_CAN_NUM > 0
+
+
+
+#endif
+ return 0; // no error
+}
+
+/////////////////////////////////////////////////////////////////////////////
+//! Initializes CAN MIDI layer
+//! \param[in] mode currently only mode 0 supported
+//! \return < 0 if initialisation failed
+//! \note Applications shouldn't call this function directly, instead please use \ref MIOS32_MIDI layer functions
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_MIDI_Init(u32 mode)
+{
+
+#if MIOS32_CAN_NUM == 0
+ return -1; // no CAN enabled
+#else
+ int i;
+
+ // currently only mode 0 supported
+ if( mode != 0 )
+ return -2; // unsupported mode
+
+#if defined MIOS32_CAN_MIDI_ENHANCED
+ MIOS32_CAN_MIDI_ModeSet(1);
+#else
+ MIOS32_CAN_MIDI_ModeSet(0);
+#endif
+
+#if defined MIOS32_CAN_MIDI_VERBOSE_LEVEL
+ // set defined verbose
+ MIOS32_CAN_MIDI_VerboseSet(MIOS32_CAN_MIDI_VERBOSE_LEVEL);
+#endif
+
+ // set active sense delay counter in mS
+ node_active_sense_ctr = 1000;
+
+ // initialize MIDI record
+ for (i=0; i<MIOS32_CAN_MIDI_NUM_PORTS; i++) {
+ MIOS32_CAN_MIDI_SysexUnpackReset(&sysex_unpack[i]);
+ MIOS32_CAN_MIDI_SysexRepackReset(&sysex_repack[i]);
+ }
+
+
+ sysex_stream_callback_func = NULL;
+
+ // if any MIDI assignment:
+#if MIOS32_CAN1_ASSIGNMENT == 1
+ // initialize CAN interface
+ if( MIOS32_CAN_Init(0) < 0 )
+ return -3; // initialisation of CAN Interface failed
+
+ // by default the Node ID is the Sysex Device ID
+ // Think about configure a different Device_ID for each of your device present on the MIDIan
+ // via the bootloader update tool.
+ //MIOS32_CAN_MIDI_NodeIDSet(MIOS32_MIDI_DeviceIDGet());
+
+ // Initialize permanent filtering for Node System Exclusive and Common messages
+ MIOS32_CAN_MIDI_FilterInit(1);
+
+
+#endif
+
+ return 0; // no error
+#endif
+}
+
+/////////////////////////////////////////////////////////////////////////////
+//! Initializes CAN MIDI layer
+//! \param[in] mode currently only mode 0 supported
+//! \return < 0 if initialisation failed
+//! \note Applications shouldn't call this function directly, instead please use \ref MIOS32_MIDI layer functions
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_MIDI_VerboseSet(u8 level)
+{
+#if MIOS32_CAN_NUM == 0
+ return -1; // no CAN enabled
+#else
+
+ can_midi_verbose = level;
+ MIOS32_CAN_VerboseSet(level); // they are independant e.g. CAN is used but not for midi purpose
+ return 0; // no error
+#endif
+}
+
+/////////////////////////////////////////////////////////////////////////////
+//! Initializes CAN MIDI layer
+//! \param[in] mode currently only mode 0 supported
+//! \return < 0 if initialisation failed
+//! \note Applications shouldn't call this function directly, instead please use \ref MIOS32_MIDI layer functions
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_MIDI_VerboseGet(void)
+{
+#ifndef MIOS32_CAN_MIDI_VERBOSE_LEVEL
+ return 0;
+#else
+#if MIOS32_CAN_NUM == 0
+ return -1; // no CAN enabled
+#else
+ return can_midi_verbose; // no error
+#endif
+#endif
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+// Changes the Node ID, Default startup Id is the Device_Id
+// IN: node_id: configures the CAN_MIDI Node ID
+// MIDIan has no master and slave ID node
+// OUT: returns < 0 if configuration failed
+// Note id is the same for both CAN
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_MIDI_NodeIDSet(u8 node_id)
+{
+#ifndef MIOS32_CAN_MIDI_VERBOSE_LEVEL
+ return 0;
+#else
+#if MIOS32_CAN_NUM == 0
+ return -1; // no CAN enabled
+#else
+
+ // my node_id must be 0..127
+ if( node_id >= 128 )
+ return -1;
+
+ // take over node ID
+ mios32_mcan_id = node_id;
+
+ return 0; // no error
+#endif
+#endif
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+// Returns the Node ID
+// IN: -
+// OUT: if -1: node not configured yet
+// if >= 0: node ID
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_MIDI_NodeIDGet(void)
+{
+#if MIOS32_CAN_NUM == 0
+ return -1; // no CAN enabled
+#else
+ return mios32_mcan_id;
+#endif
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// Changes the Node ID, Default startup Id is the Device_Id
+// IN: node_id: configures the CAN_MIDI Node ID
+// MIDIan has no master and slave ID node
+// OUT: returns < 0 if configuration failed
+// Note id is the same for both CAN
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_MIDI_ModeSet(u8 mode)
+{
+#if MIOS32_CAN_NUM == 0
+ return -1; // no CAN enabled
+#else
+ mios32_mcan_enhanced = 0;
+ if(mode)mios32_mcan_enhanced = 1;
+
+ return 0; // no error
+#endif
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+// Returns the Node ID
+// IN: -
+// OUT: if -1: node not configured yet
+// if >= 0: node ID
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_MIDI_ModeGet(void)
+{
+#if MIOS32_CAN_NUM == 0
+ return -1; // no CAN enabled
+#else
+ return mios32_mcan_enhanced;
+#endif
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+//! Initializes CAN MIDI layer
+//! \param[in] bypass 0:off, >=1:on
+//! \return < 0 if initialisation failed
+//! \note Applications shouldn't call this function directly, instead please use \ref MIOS32_MIDI layer functions
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_MIDI_FilterInit(u8 bypass)
+{
+#if MIOS32_CAN_NUM == 0
+ return -1; // no CAN enabled
+#else
+
+ //u8 i;
+ //can_ext_filter_t filt32;
+ can_std_filter_t filt16[2];
+
+// /* Node System messages and bypass -> Fifo0 */
+// // filter Bank#0, checks for incoming Node SysEx and SysCom messages
+// filt32.filt.ALL = 0;
+// filt32.filt.event = 0xf8;
+// //filt32.filt.dst_devid = mios32_mcan_id;
+// filt32.filt.ide = 1; // 29bits extented id
+// filt32.mask.ALL = 0;
+// filt32.mask.event = 0xf8; // =>0xf8 only
+// //filt32.mask.dst_devid = 0x7f;
+// filt32.mask.ide = 1;
+// MIOS32_CAN_Init32bitFilter(0, 0, filt32, 1); // CAN1, FIFO0, filter, enabled
+
+ // filter Bank#1, checks for incoming Node System Common and bypass
+
+
+ filt16[0].filt.ALL = 0; // Second 16bit filter is a Bypass filter
+ //this 11bit id must never happen.
+ //filt16[0].mask.event = (bypass ? 0x00 : 0xff); // 0xff: bypass off, 0x00: bypass on.
+ filt16[0].mask.ALL = 0x00;
+
+ filt16[1].filt.ALL = 0; // Second not used
+ filt16[1].mask.ALL = 0x00;
+ MIOS32_CAN_Init16bitFilter(0, 0, filt16[0], filt16[1], 1); // CAN1, FIFO0, filter, enabled
+
+// /* Device System messages and Real Time -> Fifo0 */
+// // filter Bank#2, checks for incoming Device(s) SysEx messages
+// filt32.filt.ALL = 0;
+// filt32.filt.event = 0xf0;
+// filt32.filt.ide = 1; // 29bits extented id
+// filt32.mask.ALL = 0;
+// filt32.mask.event = 0xff; // =>0xf0 only
+// filt32.mask.ide = 1;
+// MIOS32_CAN_Init32bitFilter(2, 0, filt32, 1); // CAN1, FIFO0, filter, enabled
+//
+// // filter Bank#3, checks for incoming Device System Common and Real Time
+// filt16[0].filt.ALL = 0; // first 16bit filter, Device SysCom
+// filt16[0].filt.event = 0xf0;
+// filt16[0].mask.ALL = 0;
+// filt16[0].mask.event = 0xf8; // =>0xf1...0xf7
+//
+// filt16[1].filt.ALL = 0; // Second 16bit filter, Real Time
+// filt16[1].filt.event = 0x78;
+// filt16[1].filt.ide = 0; // 11bits standard id
+// filt16[1].mask.ALL = 0;
+// filt16[1].mask.event = 0xf8; // =>0x78...0x7f
+// filt16[1].mask.ide = 0;
+// MIOS32_CAN_Init16bitFilter(3, 0, filt16[0], filt16[1], 1); // CAN1, FIFO0, filter, enabled
+//
+// /* Device Voicing messages -> Fifo1 */
+// // filter Bank#0x7..0xd , checks for incoming Device Channel Voice messages
+// filt32.filt.ALL = 0;
+// filt32.filt.ide = 1; // 29bits extented id
+// filt32.mask.ALL = 0;
+// filt32.mask.status = 0xf;
+// filt32.mask.ide = 1;
+// for (i=0x8; i<=0xe; i++) {
+// filt32.filt.status = i;
+// MIOS32_CAN_Init32bitFilter(i-1, 1, filt32, 1); // CAN1, FIFO0, filter, enabled
+// }
+ return 0; // no error
+#endif
+}
+
+/////////////////////////////////////////////////////////////////////////////
+//! This function can be used to determine, if a CAN interface is available
+//! \param[in] can_port CAN number (0..2)
+//! \return 1: interface available
+//! \return 0: interface not available
+//! \note Applications shouldn't call this function directly, instead please use \ref MIOS32_MIDI layer functions
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_MIDI_CheckAvailable(u8 cable)
+{
+#if MIOS32_CAN_NUM == 0
+ return -1; // all CANs explicitely disabled
+#else
+ if (MIOS32_CAN_IsAssignedToMIDI(0) == 0) // CAN assigned to MIDI?
+ return 0;
+ if( (cable & 0x0f) >= MIOS32_CAN_MIDI_NUM_PORTS )
+ return 0;
+#endif
+ return 1;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+//! This function should be called periodically each mS to handle timeout
+//! and expire counters.
+//!
+//! Not for use in an application - this function is called from
+//! MIOS32_MIDI_Periodic_mS(), which is called by a task in the programming
+//! model!
+//!
+//! \return < 0 on errors
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_MIDI_Periodic_mS(void)
+{
+#if MIOS32_CAN_NUM == 0
+ return -1; // all CANs explicitely disabled
+#else
+ u8 cable;
+
+ MIOS32_IRQ_Disable();
+ for(cable=0; cable<MIOS32_CAN_MIDI_NUM_PORTS; cable++) {
+ // simplify addressing of sysex record
+ sysex_repack_rec_t *rpk = &sysex_repack[cable];
+ sysex_unpack_rec_t *upk = &sysex_unpack[cable];
+ // // increment the expire counters for running status optimisation.
+ // //
+ // // The running status will expire after 1000 ticks (1 second)
+ // // to ensure, that the current status will be sent at least each second
+ // // to cover the case that the MIDI cable is (re-)connected during runtime.
+ // if( rs_expire_ctr[can_port] < 65535 )
+ // ++rs_expire_ctr[can_port];
+
+ // increment timeout counter for incoming packages
+ // an incomplete event will be timed out after 1000 ticks (1 second)
+ if( rpk->timeout_ctr < 65535 )
+ rpk->timeout_ctr++;
+ if( upk->timeout_ctr < 65535 )
+ upk->timeout_ctr++;
+ }
+ MIOS32_IRQ_Enable();
+ // (atomic operation not required in MIOS32_CAN_MIDI_PackageSend_NonBlocking() due to single-byte accesses)
+ if(can_midi_verbose == 0) return 0; // no error
+ if( (--node_active_sense_ctr) <=0 ){
+ node_active_sense_ctr = 1000; // every second
+ u32 new_frame_rate;
+ if( MIOS32_CAN_MIDI_CheckAvailable(0) ){
+
+ can_stat_report_t report;
+ MIOS32_CAN_ReportGetCurr(0, &report);
+
+ new_frame_rate = report.rx_packets_ctr - can_last_baudrate;
+ can_last_baudrate = report.rx_packets_ctr;
+ if(frame_rate != new_frame_rate){
+ frame_rate = new_frame_rate;
+ u8 percent =(u8)(new_frame_rate /245);
+ MIOS32_MIDI_SendDebugMessage("[MIOS32_CAN_MIDI_Periodic_mS] framerate: %d f/s, %d%%", new_frame_rate, percent);
+ }
+
+ mios32_midi_package_t p;
+ p.ALL = 0;
+ p.cin = 0x5;
+ p.cable = 0x0;
+ p.evnt0 = 0xfe ; // active sense
+
+ MIOS32_CAN_MIDI_PackageSend(p);
+ //MIOS32_CAN_MIDI_PacketTransmit(0, p);
+ }
+}
+
+#endif
+
+ return 0; // no error
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+//! This function transfers a new MCAN packet to the selected MCAN port
+//! \param[in] MCAN Packet
+//! \return 0: no error
+//! \return -1: CAN_MIDI device not available
+//! \return -2: CAN_MIDI buffer is full
+//! caller should retry until buffer is free again
+//! \note Applications shouldn't call this function directly, instead please use \ref MIOS32_MIDI layer functions
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_MIDI_PacketTransmit_NonBlocking(mcan_packet_t p)
+{
+#if MIOS32_CAN_NUM == 0
+ return -1; // all CANs explicitely disabled
+#else
+ // tx enabler bit
+ p.id.txrq = 1;
+#if defined(MIOS32_CAN_MIDI_VERBOSE_LEVEL)
+ if(can_midi_verbose>=3){DEBUG_MSG("[MIOS32_CAN_MIDI_PacketTransmit] [0x%02x][0x%02x][0x%02x][0x%02x][0x%02x][0x%02x][0x%02x][0x%02x]\n", p.data.bytes[0],p.data.bytes[1],p.data.bytes[2],p.data.bytes[3],p.data.bytes[4],p.data.bytes[5],p.data.bytes[6],p.data.bytes[7]);}
+#endif
+ switch( MIOS32_CAN_TxBufferPut(0, p.packet) ) {
+ //switch( MIOS32_CAN_Transmit(can_port, p, 0) ) {
+ case 0 ... 2: return 0; // transfer successfull
+ case -1: return -1;
+ case -2: return -2; // buffer full, request retry
+ case -3: return -3; // CAN bus error
+ default: return -4; // CAN not available
+ }
+
+#endif
+}
+
+/////////////////////////////////////////////////////////////////////////////
+//! This function transfers a new MCAN packet to the selected MCAN port
+//! (blocking function)
+//! \param[in] MCAN Packet
+//! \return 0: no error
+//! \return -1: CAN_MIDI device not available
+//! \note Applications shouldn't call this function directly, instead please use \ref MIOS32_MIDI layer functions
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_MIDI_PacketTransmit(mcan_packet_t p)
+{
+ s32 error;
+
+ while( (error=MIOS32_CAN_MIDI_PacketTransmit_NonBlocking(p)) == -2);
+
+ return error;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+//! This function formats and transfers a new MCAN packet to the selected MCAN port
+//! \param[in] header MCAN Extra Infos
+//! \param[in] package MIDI package
+//! \return 0: no error
+//! \note Applications shouldn't call this function directly, instead please use \ref MIOS32_MIDI layer functions
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_MIDI_PacketSend_NonBlocking(mcan_header_t header, mios32_midi_package_t package)
+{
+#if MIOS32_CAN_NUM == 0
+ return -1; // all CANs explicitely disabled
+#else
+ // exit if MCANx port not available
+ if( !MIOS32_CAN_MIDI_CheckAvailable(package.cable) )
+ return -3;
+
+ s32 error = 0;
+
+ // Parse package to Sysex repack
+ // notes: see "const u8 mios32_mcan_pcktype_num_bytes[16]"
+ if(package.evnt0 == 0xf0 && package.type == 0x4) {
+ //header.cin_cable = 0x40 + package.cable; // Start
+ error = MIOS32_CAN_MIDI_SysexRepackSend(header, package);
+ return error;
+ }else if(package.type == 0x4) {
+ //header.cin_cable = 0x60 + package.cable; // Cont
+ error = MIOS32_CAN_MIDI_SysexRepackSend(header, package);
+ return error;
+ }else if(package.type == 0x5 && package.evnt0 == 0xf7){
+ //header.cin_cable = 0x70 + package.cable; // end
+ error = MIOS32_CAN_MIDI_SysexRepackSend(header, package);
+ return error;
+ }else if(package.type == 0x6 || package.type == 0x7){
+ //header.cin_cable = 0x70 + package.cable; // end
+ error = MIOS32_CAN_MIDI_SysexRepackSend(header, package);
+ return error;
+ }else{ // This is not Sysex
+ mcan_packet_t p;
+ //p.frame_id = header.frame_id;
+ u8* byte = &p.data.bytes[0];
+ p.ctrl.dlc = 0;
+#if defined(MIOS32_CAN_MIDI_ENHANCED)
+ // On extended frame adds the src/dst ports infos
+ if(header.is_extended == 1){
+ *byte++ = header.dst_port;
+ *byte++ = header.src_port;
+ p.ctrl.dlc += 2;
+ }
+#endif
+ // Adds data depending on expected bytes
+ u8 expected_bytes = mios32_midi_pcktype_num_bytes[header.type];
+ switch (expected_bytes) {
+ case 1:
+ *byte = package.evnt0;
+ p.ctrl.dlc += expected_bytes;
+ break;
+ case 2:
+ *byte++ = package.evnt0;
+ *byte = package.evnt1;
+ p.ctrl.dlc += expected_bytes;
+ break;
+ case 3:
+ *byte++ = package.evnt0;
+ *byte++ = package.evnt1;
+ *byte = package.evnt2;
+ p.ctrl.dlc += expected_bytes;
+ break;
+ default:
+ return -4; // wrong datas
+ }
+ p.id = header.id;
+ while( (error = MIOS32_CAN_MIDI_PacketTransmit_NonBlocking(p)) == -2);
+#if defined(MIOS32_CAN_MIDI_VERBOSE_LEVEL)
+ if(can_midi_verbose>=2){DEBUG_MSG("[MIOS32_CAN_MIDI_PacketSend] type:0x%02x, cable:%d, ide:%d, dlc:%d, package:0x%08x\n", header.type, header.cable, header.is_extended, p.ctrl.dlc, package.ALL);}
+#endif
+ return error;
+ }
+ return error;
+
+#endif
+}
+
+/////////////////////////////////////////////////////////////////////////////
+//! This function formats and transfers a new MCAN packet to the selected MCAN port
+//! (blocking function)
+//! \param[in] header MCAN Extra Infos
+//! \param[in] package MIDI package
+//! \return 0: no error
+//! \return -1: CAN_MIDI device not available
+//! \note Applications shouldn't call this function directly, instead please use \ref MIOS32_MIDI layer functions
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_MIDI_PacketSend(mcan_header_t header, mios32_midi_package_t package)
+{
+ s32 error;
+ //DEBUG_MSG("[MIOS32_CAN_MIDI_PackageSend] 0x%08x\n", package.ALL);
+
+ while( (error=MIOS32_CAN_MIDI_PacketSend_NonBlocking(header, package)) == -2);
+
+ return error;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+//! This function sends a new MIDI package to the selected MCAN port
+//! \param[in] package MIDI package
+//! \return 0: no error
+//! \note Applications shouldn't call this function directly, instead please use \ref MIOS32_MIDI layer functions
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_MIDI_PackageSend_NonBlocking(mios32_midi_package_t package)
+{
+ s32 error;
+
+ mcan_header_t header;
+ MIOS32_CAN_MIDI_DefaultHeaderInit(&header);
+ header.cable = package.cable;
+ header.type = package.type;
+ error = MIOS32_CAN_MIDI_PacketSend_NonBlocking(header, package);
+
+ return error;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+//! This function sends a new MIDI package to the selected CAN_MIDI port
+//! (blocking function)
+//! \param[in] package MIDI package
+//! \return 0: no error
+//! \return -1: CAN_MIDI device not available
+//! \note Applications shouldn't call this function directly, instead please use \ref MIOS32_MIDI layer functions
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_MIDI_PackageSend(mios32_midi_package_t package)
+{
+ s32 error;
+
+ while( (error=MIOS32_CAN_MIDI_PackageSend_NonBlocking(package)) == -2);
+
+ return error;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+//! This function repacks a Sysex MIDI Package to a MCAN Sysex Packet
+//! It groups the 3 bytes packages in 8 bytes packet(s) and send it to the can back to back
+//! (blocking function)
+//! \param[in] header MCAN Extra Infos
+//! \param[in] package MIDI package
+//! \return 0: no error
+//! \return -1: CAN_MIDI device not available
+//! \note Applications shouldn't call this function directly, instead please use \ref MIOS32_MIDI layer functions
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_MIDI_SysexRepackSend(mcan_header_t header, mios32_midi_package_t package)
+{
+#if MIOS32_CAN_NUM == 0
+ return -1; // all CANs explicitely disabled
+#else
+
+ // exit if MCANx port not available
+ if( !MIOS32_CAN_MIDI_CheckAvailable(header.cable) )
+ return -1;
+
+ u8 i;
+ s32 error = 0;
+
+ sysex_repack_rec_t *rpk = &sysex_repack[header.cable];// simplify addressing of sysex record
+
+ // incoming MIDI package timed out (incomplete package received)
+ if( rpk->stat.waiting && rpk->timeout_ctr > 1000 ) { // 1000 mS = 1 second
+ // stop waiting
+ MIOS32_CAN_MIDI_SysexRepackReset(rpk);
+ // notify that incomplete package has been received
+ return error;
+ }
+
+ switch (header.type) {
+
+ case 4: // Start/Cont
+ if(package.evnt0 == 0xf0){
+ if(rpk->stat.waiting!=0)return error;
+ rpk->ctr = 0; // Re-init byte and packet counters on 0xf0
+ rpk->packet = 0;
+ rpk->ext_id = header.ext_id & MIOS32_CAN_MIDI_ID_MASK;
+ // On extended frame adds the src/dst ports infos
+#if defined(MIOS32_CAN_MIDI_ENHANCED)
+ if(header.is_extended){
+ rpk->buffer[rpk->ctr++] = header.src_port;
+ rpk->buffer[rpk->ctr++] = header.dst_port;
+ }
+#endif
+ rpk->stat.waiting = 1;
+ }
+ if(rpk->stat.waiting==0)return error;
+ if(rpk->ext_id != (header.ext_id & MIOS32_CAN_MIDI_ID_MASK))return error;
+ rpk->buffer[rpk->ctr++] = package.evnt0;
+ rpk->buffer[rpk->ctr++] = package.evnt1;
+ rpk->buffer[rpk->ctr++] = package.evnt2;
+ rpk->timeout_ctr = 0;
+ break;
+ case 7: // Ends with three bytes
+ if(rpk->stat.waiting==0)return error;
+ if(rpk->ext_id != (header.ext_id & MIOS32_CAN_MIDI_ID_MASK))return error;
+ rpk->buffer[rpk->ctr++] = package.evnt0;
+ rpk->buffer[rpk->ctr++] = package.evnt1;
+ rpk->buffer[rpk->ctr++] = package.evnt2;
+ rpk->stat.ending = 1;
+ break;
+ case 6: // Ends with two bytes
+ if(rpk->stat.waiting==0)return error;
+ if(rpk->ext_id != (header.ext_id & MIOS32_CAN_MIDI_ID_MASK))return error;
+ rpk->buffer[rpk->ctr++] = package.evnt0;
+ rpk->buffer[rpk->ctr++] = package.evnt1;
+ rpk->stat.ending = 1;
+ break;
+ case 5: // Ends with a single byte
+ if(rpk->stat.waiting==0)return error;
+ if(rpk->ext_id != (header.ext_id & MIOS32_CAN_MIDI_ID_MASK))return error;
+ rpk->buffer[rpk->ctr++] = package.evnt0;
+ rpk->stat.ending = 1;
+ break;
+ default:
+ break;
+ }
+
+ if(rpk->ctr >= 8){ // a full packet is ready
+ if (rpk->packet == 0)header.type = 0x4; // =>Start
+ else header.type = 0x6; // =>Cont
+ mcan_packet_t p;
+ // copy id
+ p.id = header.id;
+ // dlc
+ p.ctrl.dlc = 8;
+ for(i=0;i<8;i++)p.data.bytes[i] = rpk->buffer[i]; // Copy to packet
+ while( (error = MIOS32_CAN_MIDI_PacketTransmit_NonBlocking(p)) == -2);
+ rpk->packet++;
+ rpk->ctr %= 8; // removes sent packet from counter
+ // shift down the remaining bytes
+ for(i=0;i<rpk->ctr;i++)rpk->buffer[i] = rpk->buffer[i+8];
+#if defined(MIOS32_CAN_MIDI_VERBOSE_LEVEL)
+ if(can_midi_verbose>=2){DEBUG_MSG("[MIOS32_CAN_MIDI_SysexRepackSend] type:0x%02x, cable:%d, ide:%d, dlc:%d\n", header.type, header.cable, header.is_extended, p.ctrl.dlc);}
+#endif
+ }
+ if(rpk->stat.ending == 1){ // this is last packet
+ if (rpk->packet == 0)header.type = 0x4; // =>Start(special case only one packet stream)
+ else header.type = 0x7; // =>End
+ mcan_packet_t p;
+ // copy id
+ p.id = header.id;
+ // dlc
+ p.ctrl.dlc = rpk->ctr;
+ for(i=0;i<rpk->ctr;i++)p.data.bytes[i] = rpk->buffer[i]; // Copy to packet
+ while( (error = MIOS32_CAN_MIDI_PacketTransmit_NonBlocking(p)) == -2);
+#if defined(MIOS32_CAN_MIDI_VERBOSE_LEVEL)
+ if(can_midi_verbose>=2){DEBUG_MSG("[MIOS32_CAN_MIDI_SysexRepackSend] type:0x%02x, cable:%d, ide:%d, dlc:%d\n", header.type, header.cable, header.is_extended, p.ctrl.dlc);}
+#endif
+ // repack reset
+ MIOS32_CAN_MIDI_SysexRepackReset(rpk);
+ }
+ return error;
+
+#endif
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+//! This function sends a Sysex Stream MIDI to the selected MCAN port
+//! It divides the stream in 8 bytes packet(s) and send it to the can back to back
+//! \param[in] header MCAN Extra Infos
+//! \param[in] stream
+//! \param[in] size of the stream
+//! \return 0: no error
+//! \return -1: CAN_MIDI device not available
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_MIDI_SysexSend_NonBlocking(mcan_header_t header, u8 *stream, u16 size)
+{
+#if MIOS32_CAN_NUM == 0
+ return -1; // all CANs explicitely disabled
+#else
+ // exit if MCANx port not available
+ if( !MIOS32_CAN_MIDI_CheckAvailable(header.cable) )
+ return -3;
+ // no bytes to send -> no error
+ if( !size )
+ return 0;
+
+ // Prepare the Packet
+ s32 error;
+ mcan_packet_t p;
+ p.ctrl.ALL = 0;
+ p.data.data_l = 0;
+ p.data.data_h = 0;
+
+ // On extended frame adds the src/dst ports
+ // infos at start of first packet.
+ if(header.is_extended){
+ size += 2;
+ }
+
+ // Calc packet number and last packet DLC
+ u16 packet_num;
+ u8 i, j, last_dlc;
+ packet_num = (u16)(size >> 3);
+ last_dlc = (u8)(size % 8);
+ if(last_dlc != 0)packet_num++;
+
+ u8* stream_ptr = &stream[0];
+ // loops packets
+ for (i=0; i<packet_num; i++) {
+ u8* byte = &p.data.bytes[0];
+ // Set DLC and type depending on packet
+ if(i == 0){ // Start
+ // On extended frame adds the src/dst ports infos
+ header.type = 0x4; // Start Flag if one unique packet(<= 8 bytes in stream)
+ if(packet_num == 1)p.ctrl.dlc = last_dlc;
+ else p.ctrl.dlc = 8;
+#if defined(MIOS32_CAN_MIDI_ENHANCED)
+ if(header.is_extended){
+ *byte++ = header.dst_port;
+ *byte++ = header.src_port;
+ for (j=0; j<(p.ctrl.dlc-2); j++)*byte++ = *stream_ptr++;
+ }else{
+ for (j=0; j<p.ctrl.dlc; j++)*byte++ = *stream_ptr++;
+ }
+#else
+ for (j=0; j<p.ctrl.dlc; j++)*byte++ = *stream_ptr++;
+#endif
+ }else if(i == (packet_num-1)){ //last packet
+ header.type = 0x7; // End
+ p.ctrl.dlc = last_dlc;
+ for (j=0; j<p.ctrl.dlc; j++)*byte++ = *stream_ptr++;
+ }else{ //others packets
+ header.type = 0x6; // Cont
+ p.ctrl.dlc = 8;
+ for (j=0; j<8; j++)*byte++ = *stream_ptr++;
+ }
+#if defined(MIOS32_CAN_MIDI_VERBOSE_LEVEL)
+ if(can_midi_verbose>=2){DEBUG_MSG("[MIOS32_CAN_MIDI_SysexSend] type:0x%02x, cable:%d, ide:%d, dlc:%d\n", header.type, header.cable, header.is_extended, p.ctrl.dlc);}
+#endif
+ p.id = header.id;
+ while( (error = MIOS32_CAN_MIDI_PacketTransmit_NonBlocking(p)) == -2);
+ if(error <0 ){
+ // it must stop cause it can not retry
+ return error;
+ }
+ }
+ return 0;
+#endif
+}
+
+/////////////////////////////////////////////////////////////////////////////
+//! This function sends a Sysex Stream MIDI to the selected CAN_MIDI port
+//! It divides the stream in 8 bytes packet(s) and send it to the can back to back
+//! (blocking function)
+//! \param[in] can_port CAN_MIDI module number (0..1)
+//! \param[in] package MIDI package
+//! \return 0: no error
+//! \return -1: CAN_MIDI device not available
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_MIDI_SysexSend(mcan_header_t header, u8 *stream, u16 size)
+{
+#if MIOS32_CAN_NUM == 0
+ return -1; // all CANs explicitely disabled - accordingly no package in buffer
+#else
+ s32 error;
+
+ while( (error=MIOS32_CAN_MIDI_SysexSend_NonBlocking(header, stream, size)) == -2);
+
+ return error;
+#endif
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+//! Installs an optional SysEx callback which is called by
+//! MIOS32_MIDI_Receive_Handler() to simplify the parsing of SysEx streams.
+//!
+//! Without this callback (or with MIOS32_MIDI_SysExCallback_Init(NULL)),
+//! SysEx messages are only forwarded to APP_MIDI_NotifyPackage() in chunks of
+//! 1, 2 or 3 bytes, tagged with midi_package.type == 0x4..0x7 or 0xf
+//!
+//! In this case, the application has to take care for different transmission
+//! approaches which are under control of the package sender. E.g., while Windows
+//! uses Package Type 4..7 to transmit a SysEx stream, PortMIDI under MacOS sends
+//! a mix of 0xf (single byte) and 0x4 (continued 3-byte) packages instead.
+//!
+//! By using the SysEx callback, the type of package doesn't play a role anymore,
+//! instead the application can parse a serial stream.
+//!
+//! MIOS32 ensures, that realtime events (0xf8..0xff) are still forwarded to
+//! APP_MIDI_NotifyPackage(), regardless if they are transmitted in a package
+//! type 0x5 or 0xf, so that the SysEx parser doesn't need to filter out such
+//! events, which could otherwise appear inside a SysEx stream.
+//!
+//! \param[in] *callback_sysex pointer to callback function:<BR>
+//! \code
+//! s32 callback_sysex(mios32_midi_port_t port, u8 sysex_byte)
+//! {
+//! //
+//! // .. parse stream
+//! //
+//!
+//! return 1; // don't forward package to APP_MIDI_NotifyPackage()
+//! }
+//! \endcode
+//! If the function returns 0, SysEx bytes will be forwarded to APP_MIDI_NotifyPackage() as well.
+//! With return value != 0, APP_MIDI_NotifyPackage() won't get the already processed package.
+//! \return < 0 on errors
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_MIDI_SysExStreamCallback_Init(s32 (*callback_sysex_stream)(mcan_header_t header, u8* stream, u16 size))
+{
+#if MIOS32_CAN_NUM == 0
+ return -1; // all CANs explicitely disabled - accordingly no package in buffer
+#else
+ sysex_stream_callback_func = callback_sysex_stream;
+
+ return 0; // no error
+#endif
+}
+
+//////////////////////////////////////////////////////////////////////////
+//! Installs an optional Direct Midi package Callback callback
+//! If the function returns 0, SysEx bytes will be forwarded to APP_MIDI_NotifyPackage() as well.
+//! With return value != 0, APP_MIDI_NotifyPackage() won't get the already processed package.
+//! \return < 0 on errors
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_MIDI_PackageCallback_Init(s32 (*direct_package_callback)(mcan_header_t header, mios32_midi_package_t package))
+{
+#if MIOS32_CAN_NUM == 0
+ return -1; // all CANs explicitely disabled - accordingly no package in buffer
+#else
+ direct_package_callback_func = direct_package_callback;
+
+ return 0; // no error
+#endif
+}
+
+/////////////////////////////////////////////////////////////////////////////
+//
+/////////////////////////////////////////////////////////////////////////////
+static s32 MIOS32_CAN_MIDI_SysexUnPack(u8 cable, mios32_midi_package_t *package)
+{
+ int i;
+ // midi repack from sysex stream
+ sysex_unpack_rec_t *upk = &sysex_unpack[cable];
+
+ if(upk->stat.ending == 1 && upk->ctr<=3){
+ switch(upk->ctr){
+ case 3:
+ package->type = 0x7; // F: tree bytes
+ package->cable = cable;
+ package->evnt0 = upk->buffer[0];
+ package->evnt1 = upk->buffer[1];
+ package->evnt2 = upk->buffer[2];
+ break;
+ case 2:
+ package->type = 0x6; // F: two bytes
+ package->cable = cable;
+ package->evnt0 = upk->buffer[0];
+ package->evnt1 = upk->buffer[1];
+ break;
+ case 1:
+ package->type = 0x5; // F: single byte
+ package->cable = cable;
+ package->evnt0 = upk->buffer[0];
+ break;
+ default:
+ break;
+ }
+ // toDo package callback
+ MIOS32_CAN_MIDI_SysexUnpackReset(upk);
+ return 1; //last package ready
+ }else if(upk->ctr>=3){
+ package->type = 0x4; // F: single byte
+ package->cable = cable;
+ package->evnt0 = upk->buffer[0];
+ package->evnt1 = upk->buffer[1];
+ package->evnt2 = upk->buffer[2];
+ upk->ctr -=3;
+ // shift down the remaining bytes
+ for(i=0;i<upk->ctr;i++)upk->buffer[i] = upk->buffer[i+3];
+ return 1;
+ }else return 0;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+//! This function checks for a new package
+//! \param[in] can_port CAN_MIDI module number (0..2)
+//! \param[out] package pointer to MIDI package (received package will be put into the given variable
+//! \return 0: no error
+//! \return -1: no package in buffer
+//! \return -10: incoming MIDI package timed out (incomplete package received)
+//! \note Applications shouldn't call this function directly, instead please use \ref MIOS32_MIDI layer functions
+/////////////////////////////////////////////////////////////////////////////
+s32 MIOS32_CAN_MIDI_PackageReceive(mios32_midi_package_t *package)
+{
+#if MIOS32_CAN_NUM == 0
+ return -1; // all CANs explicitely disabled - accordingly no package in buffer
+#else
+
+ int i;
+ s32 status = 0;
+ // clear MIDI package
+ package->ALL = 0;
+
+ // Checks for stream repack first.
+ for (i=0; i<MIOS32_CAN_MIDI_NUM_PORTS; i++) {
+ // incoming MIDI package timed out (incomplete package received)
+ if( sysex_unpack[i].stat.waiting && sysex_unpack[i].timeout_ctr > 1000 ) { // 1000 mS = 1 second
+ // stop waiting, reset
+ MIOS32_CAN_MIDI_SysexUnpackReset(&sysex_unpack[i]);
+ }
+ // there's some
+ if(sysex_unpack[i].stat.ready == 1)
+ status = MIOS32_CAN_MIDI_SysexUnPack(i, package);
+ if(status == 1)return status;
+ }
+
+ mcan_packet_t p;
+ // Something in the buffer?
+ if(MIOS32_CAN_RxBufferGet(0, &p.packet) >= 0) {
+ // usable structure
+ mcan_header_t header;
+ header.id = p.id;
+ // exit if CAN port not available
+ if( !MIOS32_CAN_MIDI_CheckAvailable(header.cable) )
+ return 0;
+// //test
+//#if defined(MIOS32_CAN_MIDI_VERBOSE_LEVEL)
+// if(can_midi_verbose>=3)DEBUG_MSG("[MIOS32_CAN_MIDI_PackageReceive] 0x%08x 0x%08x\n", header.ext_id, header.ext_id & MIOS32_CAN_MIDI_ID_MASK);
+//#endif
+ if(header.type == 0x4 || header.type == 0x6 || header.type == 0x7){
+ // simplify addressing of sysex record
+ sysex_unpack_rec_t *upk = &sysex_unpack[header.cable];
+
+#if defined(MIOS32_CAN_MIDI_VERBOSE_LEVEL)
+ if(can_midi_verbose>=2){DEBUG_MSG("[MIOS32_CAN_MIDI_PackageReceive] type:0x%02x, cable:%d, ide:%d, dlc:%d, data: 0x%08x%08x\n", header.type, header.cable, header.is_extended, p.ctrl.dlc, p.data.data_h, p.data.data_l);}
+#endif
+ status = 0;
+ switch (header.type) {
+ case 0x4:
+ // if busy filters new sysex message
+ if(upk->stat.waiting)break; // not forwarded
+ // store current stream header
+ upk->ext_id = header.ext_id & MIOS32_CAN_MIDI_ID_MASK; // Mask removes type field
+ // basic/enhanced?
+ if(header.is_extended == 1){
+#if defined(MIOS32_CAN_MIDI_ENHANCED)
+ // breaks if third byte in data is not SOX
+ if(p.data.bytes[2] != 0xf0)break;
+ // copy ports from the two first bytes of data
+ upk->ports = p.data.data[0];
+ // because of precedent lines stream counter is dlc -2
+ upk->ctr = p.ctrl.dlc -2;
+ // copy data bytes
+ for (i=0; i<upk->ctr; i++)upk->buffer[i] = p.data.bytes[i+2];
+#else
+ break;
+#endif
+ }else{
+ // breaks if first byte in data is not SOX
+ if(p.data.bytes[0] != 0xf0)break;
+ // stream counter is dlc
+ upk->ctr = p.ctrl.dlc;
+ for (i=0; i<upk->ctr; i++)upk->buffer[i] = p.data.bytes[i];
+ }
+ // Ends if last byte is EOX
+ if(p.data.bytes[p.ctrl.dlc-1] == 0xf7)upk->stat.ending = 1; // last more sysex packet-
+ else upk->stat.waiting = 1; // we are waiting for more sysex packet
+ // reset timeout
+ upk->timeout_ctr = 0;
+#if !defined(MIOS32_CAN_MIDI_SYSEX_STREAM_FIRST)
+ upk->stat.ready = 1;
+ status = MIOS32_CAN_MIDI_SysexUnPack(header.cable, package);
+#endif
+ break;
+ case 0x6 ... 0x7:
+ if(!upk->stat.waiting)break; // not forwarded
+ // compare headers, breaks if no match with stream packet
+ if(upk->ext_id != (header.ext_id & MIOS32_CAN_MIDI_ID_MASK))break; // not forwarded
+ // copy data bytes
+ for (i=0; i<p.ctrl.dlc; i++)
+ upk->buffer[upk->ctr+i] = p.data.bytes[i];
+ // adds dlc to stream counter
+ upk->ctr += p.ctrl.dlc;
+ if(header.type == 0x7)upk->stat.ending = 1; // last more sysex packet-
+ else upk->stat.waiting = 1; // we are waiting for more sysex packet
+ // reset timeout
+ upk->timeout_ctr = 0;
+#if !defined(MIOS32_CAN_MIDI_SYSEX_STREAM_FIRST)
+ upk->stat.ready = 1;
+ status = MIOS32_CAN_MIDI_SysexUnPack(header.cable, package);
+#endif
+ break;
+ default:
+ break;
+ }
+
+ if(upk->stat.ending){ //
+ //upk->ending = 0;
+ upk->stat.waiting = 0;
+#if defined(MIOS32_CAN_MIDI_SYSEX_STREAM_FIRST)
+ // Sysex stream callback if callback returns 0 then no midi repack
+ s32 callback_status = 0;
+ if( sysex_stream_callback_func != NULL ){
+ header.ext_id = upk->ext_id;
+ header.type = 0x4;
+ header.ports = upk->ports;
+ callback_status = sysex_stream_callback_func(header, upk->buffer, upk->ctr); // -> forwarded as SysEx stream
+ }
+ if(!callback_status){
+ // start packaging
+ upk->stat.ready = 1;
+ return MIOS32_CAN_MIDI_SysexUnPack(header.cable, package);
+ }else{
+ MIOS32_CAN_MIDI_SysexUnpackReset(upk);
+ return 0; // stream forwarded but no midi repack
+ }
+#else
+ return status; //last package ready
+#endif
+ }else{
+ return status; // no midi package
+ }
+
+ } else { // Others messages than Sysex
+ // prepare header
+ mcan_header_t header;
+ header.id = p.id;
+ // data pointer
+ u8* byte = &p.data.bytes[0];
+ // is enhanced packet
+ if(header.is_extended){
+#if defined(MIOS32_CAN_MIDI_ENHANCED)
+ header.src_port = *byte++;
+ header.src_port = *byte++;
+ p.ctrl.dlc -=2;
+#else
+ return 0; // not forwarded
+#endif
+ }
+ u8 expected_bytes = mios32_midi_pcktype_num_bytes[header.type];
+ if( expected_bytes == p.ctrl.dlc) { // Packet is single byte cmd, expected_bytes=0 and DLC=0
+
+ package->type = header.type;
+ package->cable = header.cable;
+ for (i=0; i<expected_bytes; i++)package->bytes[i+1] = *byte++;
+#if defined(MIOS32_CAN_MIDI_VERBOSE_LEVEL)
+ if(can_midi_verbose>=2){DEBUG_MSG("[MIOS32_CAN_MIDI_PackageReceive] type:0x%02x, cable:%d, ide:%d, dlc:%d, package:0x%08x\n", header.type, header.cable, header.is_extended, p.ctrl.dlc, package->ALL);}
+#endif
+ if(header.type == 0x0){
+ return 0;
+ }else if(header.type == 0x1){ // Local command filter
+ MIOS32_CAN_MIDI_LocalCmdParser(header, package);
+ return 0;
+ }else{
+ s32 callback_status = 0;
+ if( direct_package_callback_func != NULL ){
+ mios32_midi_package_t direct_package = *package;
+ callback_status = direct_package_callback_func(header, direct_package); // -> forwarded as MCAN Midi Package
+ }
+ if(!callback_status)return 1; // midi package ok
+ else return 0; // not forwarded
+ }
+ }else return 0; // no midi package
+ }
+ }else return -2;
+
+#endif
+}
+
+/////////////////////////////////////////////////////////////////////////////
+//
+/////////////////////////////////////////////////////////////////////////////
+u32 MIOS32_CAN_MIDI_DefaultHeaderInit(mcan_header_t* header)
+{
+#if MIOS32_CAN_NUM == 0
+ return -1; // all CANs explicitely disabled - accordingly no package in buffer
+#else
+ // reset
+ header->ext_id = 0;
+ header->ports = 0;
+
+ if(mios32_mcan_enhanced > 0)header->is_extended = 1;else header->is_extended = 0;
+ //header->is_extended = 0;
+ header->src_node = mios32_mcan_id;
+ header->src_port = MCAN0;
+ header->dst_node = MIOS32_CAN_MIDI_DEF_DEST_ID;
+ header->dst_port = MCAN0;
+ header->app_type = MIOS32_CAN_MIDI_APP_CODE;
+ header->vman_prio = MIOS32_CAN_MIDI_DEF_VMAN;
+
+ return 0; // no error
+#endif
+}
+
+//!}
+
+#endif /* MIOS32_USE_CAN_MIDI */
/mcan/mios32/common/mios32_can_midi.c
Property changes:
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property