4343
4444#if MICROPY_HW_ENABLE_CAN
4545
46+ #define MASK16 (0)
47+ #define LIST16 (1)
48+ #define MASK32 (2)
49+ #define LIST32 (3)
50+
4651/// \moduleref pyb
4752/// \class CAN - controller area network communication bus
4853///
@@ -71,6 +76,8 @@ typedef struct _pyb_can_obj_t {
7176 CAN_HandleTypeDef can ;
7277} pyb_can_obj_t ;
7378
79+ STATIC uint8_t can2_start_bank = 14 ;
80+
7481// assumes Init parameters have been set up correctly
7582STATIC bool can_init (pyb_can_obj_t * can_obj ) {
7683 CAN_TypeDef * CANx = NULL ;
@@ -136,6 +143,23 @@ STATIC void can_deinit(pyb_can_obj_t *can_obj) {
136143 }
137144}
138145
146+ STATIC void can_clearfilter (uint32_t f ) {
147+ CAN_FilterConfTypeDef filter ;
148+
149+ filter .FilterIdHigh = 0 ;
150+ filter .FilterIdLow = 0 ;
151+ filter .FilterMaskIdHigh = 0 ;
152+ filter .FilterMaskIdLow = 0 ;
153+ filter .FilterFIFOAssignment = CAN_FILTER_FIFO0 ;
154+ filter .FilterNumber = f ;
155+ filter .FilterMode = CAN_FILTERMODE_IDMASK ;
156+ filter .FilterScale = CAN_FILTERSCALE_16BIT ;
157+ filter .FilterActivation = DISABLE ;
158+ filter .BankNumber = can2_start_bank ;
159+
160+ HAL_CAN_ConfigFilter (NULL , & filter );
161+ }
162+
139163/******************************************************************************/
140164// Micro Python bindings
141165
@@ -199,20 +223,6 @@ STATIC mp_obj_t pyb_can_init_helper(pyb_can_obj_t *self, mp_uint_t n_args, const
199223 nlr_raise (mp_obj_new_exception_msg_varg (& mp_type_ValueError , "CAN port %d does not exist" , self -> can_id ));
200224 }
201225
202- // set CAN filter to accept everything
203- CAN_FilterConfTypeDef filter ;
204- filter .FilterIdHigh = 0 ;
205- filter .FilterIdLow = 0 ;
206- filter .FilterMaskIdHigh = 0 ;
207- filter .FilterMaskIdLow = 0 ;
208- filter .FilterFIFOAssignment = CAN_FILTER_FIFO0 ;
209- filter .FilterNumber = 0 ; // 0-27
210- filter .FilterMode = CAN_FILTERMODE_IDMASK ;
211- filter .FilterScale = CAN_FILTERSCALE_32BIT ;
212- filter .FilterActivation = ENABLE ;
213- filter .BankNumber = 0 ; // what's this for?
214- HAL_CAN_ConfigFilter (& self -> can , & filter );
215-
216226 return mp_const_none ;
217227}
218228
@@ -399,13 +409,136 @@ STATIC mp_obj_t pyb_can_recv(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_
399409}
400410STATIC MP_DEFINE_CONST_FUN_OBJ_KW (pyb_can_recv_obj , 1 , pyb_can_recv );
401411
412+ /// \class method initfilterbanks
413+ ///
414+ /// Set up the filterbanks. All filter will be disabled and set to their reset states.
415+ ///
416+ /// - `banks` is an integer that sets how many filter banks that are reserved for CAN1.
417+ /// 0 -> no filters assigned for CAN1
418+ /// 28 -> all filters are assigned to CAN1
419+ /// CAN2 will get the rest of the 28 available.
420+ ///
421+ /// Return value: none.
422+ STATIC mp_obj_t pyb_can_initfilterbanks (mp_obj_t self , mp_obj_t bank_in ) {
423+ can2_start_bank = mp_obj_get_int (bank_in );
424+
425+ for (int f = 0 ; f < 28 ; f ++ ) {
426+ can_clearfilter (f );
427+ }
428+
429+ return mp_const_none ;
430+ }
431+ STATIC MP_DEFINE_CONST_FUN_OBJ_2 (pyb_can_initfilterbanks_fun_obj , pyb_can_initfilterbanks );
432+ STATIC MP_DEFINE_CONST_CLASSMETHOD_OBJ (pyb_can_initfilterbanks_obj , (const mp_obj_t )& pyb_can_initfilterbanks_fun_obj );
433+
434+ STATIC mp_obj_t pyb_can_clearfilter (mp_obj_t self_in , mp_obj_t bank_in ) {
435+ pyb_can_obj_t * self = self_in ;
436+ mp_int_t f = mp_obj_get_int (bank_in );
437+ if (self -> can_id == 2 ) {
438+ f += can2_start_bank ;
439+ }
440+ can_clearfilter (f );
441+ return mp_const_none ;
442+ }
443+ STATIC MP_DEFINE_CONST_FUN_OBJ_2 (pyb_can_clearfilter_obj , pyb_can_clearfilter );
444+
445+ /// Configures a filterbank
446+ /// Return value: `None`.
447+ #define EXTENDED_ID_TO_16BIT_FILTER (id ) (((id & 0xC00000) >> 13) | ((id & 0x38000) >> 15)) | 8
448+ STATIC mp_obj_t pyb_can_setfilter (mp_uint_t n_args , const mp_obj_t * pos_args , mp_map_t * kw_args ) {
449+ static const mp_arg_t allowed_args [] = {
450+ { MP_QSTR_bank , MP_ARG_REQUIRED | MP_ARG_INT , {.u_int = 0 } },
451+ { MP_QSTR_mode , MP_ARG_REQUIRED | MP_ARG_INT , {.u_int = 0 } },
452+ { MP_QSTR_fifo , MP_ARG_REQUIRED | MP_ARG_INT , {.u_int = CAN_FILTER_FIFO0 } },
453+ { MP_QSTR_params , MP_ARG_REQUIRED | MP_ARG_OBJ , {.u_obj = MP_OBJ_NULL } },
454+ };
455+
456+ // parse args
457+ pyb_can_obj_t * self = pos_args [0 ];
458+ mp_arg_val_t args [MP_ARRAY_SIZE (allowed_args )];
459+ mp_arg_parse_all (n_args - 1 , pos_args + 1 , kw_args , MP_ARRAY_SIZE (allowed_args ), allowed_args , args );
460+
461+ mp_uint_t len ;
462+ mp_obj_t * params ;
463+ mp_obj_get_array (args [3 ].u_obj , & len , & params );
464+
465+ CAN_FilterConfTypeDef filter ;
466+ if (args [1 ].u_int == MASK16 || args [1 ].u_int == LIST16 ) {
467+ if (len != 4 ) {
468+ goto error ;
469+ }
470+ filter .FilterScale = CAN_FILTERSCALE_16BIT ;
471+ if (self -> extframe ) {
472+ filter .FilterIdLow = EXTENDED_ID_TO_16BIT_FILTER (mp_obj_get_int (params [0 ])); // id1
473+ filter .FilterMaskIdLow = EXTENDED_ID_TO_16BIT_FILTER (mp_obj_get_int (params [1 ])); // mask1
474+ filter .FilterIdHigh = EXTENDED_ID_TO_16BIT_FILTER (mp_obj_get_int (params [2 ])); // id2
475+ filter .FilterMaskIdHigh = EXTENDED_ID_TO_16BIT_FILTER (mp_obj_get_int (params [3 ])); // mask2
476+ } else {
477+ filter .FilterIdLow = mp_obj_get_int (params [0 ]) << 5 ; // id1
478+ filter .FilterMaskIdLow = mp_obj_get_int (params [1 ]) << 5 ; // mask1
479+ filter .FilterIdHigh = mp_obj_get_int (params [2 ]) << 5 ; // id2
480+ filter .FilterMaskIdHigh = mp_obj_get_int (params [3 ]) << 5 ; // mask2
481+ }
482+ if (args [1 ].u_int == MASK16 ) {
483+ filter .FilterMode = CAN_FILTERMODE_IDMASK ;
484+ }
485+ if (args [1 ].u_int == LIST16 ) {
486+ filter .FilterMode = CAN_FILTERMODE_IDLIST ;
487+ }
488+ }
489+ else if (args [1 ].u_int == MASK32 || args [1 ].u_int == LIST32 ) {
490+ if (len != 2 ) {
491+ goto error ;
492+ }
493+ filter .FilterScale = CAN_FILTERSCALE_32BIT ;
494+
495+ filter .FilterIdHigh = (mp_obj_get_int (params [0 ]) & 0xFF00 ) >> 13 ;
496+ filter .FilterIdLow = ((mp_obj_get_int (params [0 ]) & 0x00FF ) << 3 ) | 4 ;
497+ filter .FilterMaskIdHigh = (mp_obj_get_int (params [1 ]) & 0xFF00 ) >> 13 ;
498+ filter .FilterMaskIdLow = ((mp_obj_get_int (params [1 ]) & 0x00FF ) << 3 ) | 4 ;
499+ if (args [1 ].u_int == MASK32 ) {
500+ filter .FilterMode = CAN_FILTERMODE_IDMASK ;
501+ }
502+ if (args [1 ].u_int == LIST32 ) {
503+ filter .FilterMode = CAN_FILTERMODE_IDLIST ;
504+ }
505+ } else {
506+ goto error ;
507+ }
508+
509+ filter .FilterFIFOAssignment = args [2 ].u_int ; // fifo
510+ filter .FilterNumber = args [0 ].u_int ; // bank
511+ if (self -> can_id == 1 ) {
512+ if (filter .FilterNumber >= can2_start_bank ) {
513+ goto error ;
514+ }
515+ } else {
516+ filter .FilterNumber = filter .FilterNumber + can2_start_bank ;
517+ if (filter .FilterNumber > 27 ) {
518+ goto error ;
519+ }
520+ }
521+ filter .FilterActivation = ENABLE ;
522+ filter .BankNumber = can2_start_bank ;
523+ HAL_CAN_ConfigFilter (& self -> can , & filter );
524+
525+ return mp_const_none ;
526+
527+ error :
528+ nlr_raise (mp_obj_new_exception_msg_varg (& mp_type_ValueError , "CAN filter parameter error" ));
529+ }
530+ STATIC MP_DEFINE_CONST_FUN_OBJ_KW (pyb_can_setfilter_obj , 1 , pyb_can_setfilter );
531+
402532STATIC const mp_map_elem_t pyb_can_locals_dict_table [] = {
403533 // instance methods
404534 { MP_OBJ_NEW_QSTR (MP_QSTR_init ), (mp_obj_t )& pyb_can_init_obj },
405535 { MP_OBJ_NEW_QSTR (MP_QSTR_deinit ), (mp_obj_t )& pyb_can_deinit_obj },
406536 { MP_OBJ_NEW_QSTR (MP_QSTR_any ), (mp_obj_t )& pyb_can_any_obj },
407537 { MP_OBJ_NEW_QSTR (MP_QSTR_send ), (mp_obj_t )& pyb_can_send_obj },
408538 { MP_OBJ_NEW_QSTR (MP_QSTR_recv ), (mp_obj_t )& pyb_can_recv_obj },
539+ { MP_OBJ_NEW_QSTR (MP_QSTR_initfilterbanks ), (mp_obj_t )& pyb_can_initfilterbanks_obj },
540+ { MP_OBJ_NEW_QSTR (MP_QSTR_setfilter ), (mp_obj_t )& pyb_can_setfilter_obj },
541+ { MP_OBJ_NEW_QSTR (MP_QSTR_clearfilter ), (mp_obj_t )& pyb_can_clearfilter_obj },
409542
410543 // class constants
411544 // Note: we use the ST constants >> 4 so they fit in a small-int. The
@@ -414,6 +547,11 @@ STATIC const mp_map_elem_t pyb_can_locals_dict_table[] = {
414547 { MP_OBJ_NEW_QSTR (MP_QSTR_LOOPBACK ), MP_OBJ_NEW_SMALL_INT (CAN_MODE_LOOPBACK >> 4 ) },
415548 { MP_OBJ_NEW_QSTR (MP_QSTR_SILENT ), MP_OBJ_NEW_SMALL_INT (CAN_MODE_SILENT >> 4 ) },
416549 { MP_OBJ_NEW_QSTR (MP_QSTR_SILENT_LOOPBACK ), MP_OBJ_NEW_SMALL_INT (CAN_MODE_SILENT_LOOPBACK >> 4 ) },
550+
551+ { MP_OBJ_NEW_QSTR (MP_QSTR_MASK16 ), MP_OBJ_NEW_SMALL_INT (MASK16 ) },
552+ { MP_OBJ_NEW_QSTR (MP_QSTR_LIST16 ), MP_OBJ_NEW_SMALL_INT (LIST16 ) },
553+ { MP_OBJ_NEW_QSTR (MP_QSTR_MASK32 ), MP_OBJ_NEW_SMALL_INT (MASK32 ) },
554+ { MP_OBJ_NEW_QSTR (MP_QSTR_LIST32 ), MP_OBJ_NEW_SMALL_INT (LIST32 ) },
417555};
418556
419557STATIC MP_DEFINE_CONST_DICT (pyb_can_locals_dict , pyb_can_locals_dict_table );
0 commit comments