_canio: Minimal implementation for SAM E5x MCUs

Tested & working:

 * Send standard packets
 * Receive standard packets (1 FIFO, no filter)

Interoperation between SAM E54 Xplained running this tree and
MicroPython running on STM32F405 Feather with an external
transceiver was also tested.

Many other aspects of a full implementation are not yet present,
such as error detection and recovery.
This commit is contained in:
Jeff Epler 2020-08-20 11:08:00 -05:00
parent e7a213a114
commit a2e1867f69
30 changed files with 2190 additions and 3 deletions

8
main.c
View File

@ -81,6 +81,10 @@
#include "supervisor/shared/bluetooth.h" #include "supervisor/shared/bluetooth.h"
#endif #endif
#if CIRCUITPY_CANIO
#include "common-hal/_canio/CAN.h"
#endif
void do_str(const char *src, mp_parse_input_kind_t input_kind) { void do_str(const char *src, mp_parse_input_kind_t input_kind) {
mp_lexer_t *lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, src, strlen(src), 0); mp_lexer_t *lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, src, strlen(src), 0);
if (lex == NULL) { if (lex == NULL) {
@ -226,6 +230,10 @@ void cleanup_after_vm(supervisor_allocation* heap) {
free_memory(heap); free_memory(heap);
supervisor_move_memory(); supervisor_move_memory();
#ifdef CIRCUITPY_CANIO
common_hal_canio_reset();
#endif
reset_port(); reset_port();
#if CIRCUITPY_BOARD #if CIRCUITPY_BOARD
reset_board_busses(); reset_board_busses();

View File

@ -393,6 +393,10 @@ SRC_QSTR += $(HEADER_BUILD)/sdiodata.h
$(HEADER_BUILD)/sdiodata.h: tools/mksdiodata.py | $(HEADER_BUILD) $(HEADER_BUILD)/sdiodata.h: tools/mksdiodata.py | $(HEADER_BUILD)
$(Q)$(PYTHON3) $< > $@ $(Q)$(PYTHON3) $< > $@
SRC_QSTR += $(HEADER_BUILD)/candata.h
$(HEADER_BUILD)/candata.h: tools/mkcandata.py | $(HEADER_BUILD)
$(Q)$(PYTHON3) $< > $@
SRC_QSTR += $(SRC_C) $(SRC_SUPERVISOR) $(SRC_COMMON_HAL_EXPANDED) $(SRC_SHARED_MODULE_EXPANDED) SRC_QSTR += $(SRC_C) $(SRC_SUPERVISOR) $(SRC_COMMON_HAL_EXPANDED) $(SRC_SHARED_MODULE_EXPANDED)
# Sources that only hold QSTRs after pre-processing. # Sources that only hold QSTRs after pre-processing.
SRC_QSTR_PREPROCESSOR += peripherals/samd/$(PERIPHERALS_CHIP_FAMILY)/clocks.c SRC_QSTR_PREPROCESSOR += peripherals/samd/$(PERIPHERALS_CHIP_FAMILY)/clocks.c

View File

@ -1165,6 +1165,88 @@
#define CONF_SDHC1_SLOW_FREQUENCY 12000000 #define CONF_SDHC1_SLOW_FREQUENCY 12000000
#endif #endif
// <h> CAN Clock Settings
// <y> CAN Clock source
// <GCLK_PCHCTRL_GEN_GCLK0_Val"> Generic clock generator 0
// <GCLK_PCHCTRL_GEN_GCLK1_Val"> Generic clock generator 1
// <GCLK_PCHCTRL_GEN_GCLK2_Val"> Generic clock generator 2
// <GCLK_PCHCTRL_GEN_GCLK3_Val"> Generic clock generator 3
// <GCLK_PCHCTRL_GEN_GCLK4_Val"> Generic clock generator 4
// <GCLK_PCHCTRL_GEN_GCLK5_Val"> Generic clock generator 5
// <GCLK_PCHCTRL_GEN_GCLK6_Val"> Generic clock generator 6
// <GCLK_PCHCTRL_GEN_GCLK7_Val"> Generic clock generator 7
// <GCLK_PCHCTRL_GEN_GCLK8_Val"> Generic clock generator 8
// <GCLK_PCHCTRL_GEN_GCLK9_Val"> Generic clock generator 9
// <GCLK_PCHCTRL_GEN_GCLK10_Val"> Generic clock generator 10
// <GCLK_PCHCTRL_GEN_GCLK11_Val"> Generic clock generator 11
// <i> Select the clock source for CAN.
// <id> sdhc_gclk_selection
#ifndef CONF_GCLK_CAN0_SRC
#define CONF_GCLK_CAN0_SRC GCLK_PCHCTRL_GEN_GCLK0_Val
#endif
/**
* \def CAN FREQUENCY
* \brief CAN's Clock frequency
*/
#ifndef CONF_CAN0_FREQUENCY
#define CONF_CAN0_FREQUENCY 120000000
#endif
// <h> CAN Clock Settings
// <y> CAN Clock source
// <GCLK_PCHCTRL_GEN_GCLK0_Val"> Generic clock generator 0
// <GCLK_PCHCTRL_GEN_GCLK1_Val"> Generic clock generator 1
// <GCLK_PCHCTRL_GEN_GCLK2_Val"> Generic clock generator 2
// <GCLK_PCHCTRL_GEN_GCLK3_Val"> Generic clock generator 3
// <GCLK_PCHCTRL_GEN_GCLK4_Val"> Generic clock generator 4
// <GCLK_PCHCTRL_GEN_GCLK5_Val"> Generic clock generator 5
// <GCLK_PCHCTRL_GEN_GCLK6_Val"> Generic clock generator 6
// <GCLK_PCHCTRL_GEN_GCLK7_Val"> Generic clock generator 7
// <GCLK_PCHCTRL_GEN_GCLK8_Val"> Generic clock generator 8
// <GCLK_PCHCTRL_GEN_GCLK9_Val"> Generic clock generator 9
// <GCLK_PCHCTRL_GEN_GCLK10_Val"> Generic clock generator 10
// <GCLK_PCHCTRL_GEN_GCLK11_Val"> Generic clock generator 11
// <i> Select the clock source for CAN.
// <id> sdhc_gclk_selection
#ifndef CONF_GCLK_CAN1_SRC
#define CONF_GCLK_CAN1_SRC GCLK_PCHCTRL_GEN_GCLK0_Val
#endif
/**
* \def CAN FREQUENCY
* \brief CAN's Clock frequency
*/
#ifndef CONF_CAN1_FREQUENCY
#define CONF_CAN1_FREQUENCY 120000000
#endif
// <<< end of configuration section >>> // <<< end of configuration section >>>
#endif // PERIPHERAL_CLK_CONFIG_H #endif // PERIPHERAL_CLK_CONFIG_H

View File

@ -51,6 +51,7 @@ SECTIONS
{ {
. = ALIGN(4); . = ALIGN(4);
_srelocate = .; /* create a global symbol at data start; used by startup code in order to initialize the .data section in RAM */ _srelocate = .; /* create a global symbol at data start; used by startup code in order to initialize the .data section in RAM */
. = ALIGN(4);
*(.ramfunc) *(.ramfunc)
*(.ramfunc*) *(.ramfunc*)
*(.data) /* .data sections */ *(.data) /* .data sections */
@ -61,11 +62,15 @@ SECTIONS
} >RAM } >RAM
/* Uninitialized data section */ /* Uninitialized data section */
.bss : .bss (NOLOAD) :
{ {
. = ALIGN(4); . = ALIGN(4);
_sbss = .; _sbss = .;
_szero = .; /* define a global symbol at bss start; used by startup code */ _szero = .; /* define a global symbol at bss start; used by startup code */
/* Data accessed by the CAN peripheral must be in the first 64kB RAM */
_scanram = .;
*(.canram)
_ecanram = .;
*(.bss) *(.bss)
*(.bss*) *(.bss*)
*(COMMON) *(COMMON)

View File

@ -12,3 +12,4 @@ EXTERNAL_FLASH_DEVICES = "N25Q256A"
LONGINT_IMPL = MPZ LONGINT_IMPL = MPZ
CIRCUITPY_SDIOIO = 1 CIRCUITPY_SDIOIO = 1
CIRCUITPY_CANIO = 1

View File

@ -48,8 +48,9 @@ STATIC const mp_rom_map_elem_t board_global_dict_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_QT), MP_ROM_PTR(&pin_PA16) }, { MP_OBJ_NEW_QSTR(MP_QSTR_QT), MP_ROM_PTR(&pin_PA16) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_CANRX), MP_ROM_PTR(&pin_PB12) }, { MP_OBJ_NEW_QSTR(MP_QSTR_CAN_RX), MP_ROM_PTR(&pin_PB13) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_CANTX), MP_ROM_PTR(&pin_PB13) }, { MP_OBJ_NEW_QSTR(MP_QSTR_CAN_TX), MP_ROM_PTR(&pin_PB12) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_CAN_STANDBY), MP_ROM_PTR(&pin_PC13) },
// EXT1 header // EXT1 header
{ MP_OBJ_NEW_QSTR(MP_QSTR_PB04), MP_ROM_PTR(&pin_PB04) }, { MP_OBJ_NEW_QSTR(MP_QSTR_PB04), MP_ROM_PTR(&pin_PB04) },

View File

@ -0,0 +1,384 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2020 Jeff Epler for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <string.h>
#include "py/runtime.h"
#include "py/mperrno.h"
#include "peripheral_clk_config.h"
#include "common-hal/_canio/CAN.h"
#include "shared-bindings/microcontroller/Pin.h"
#include "shared-bindings/util.h"
#include "supervisor/port.h"
#include "component/can.h"
#include "genhdr/candata.h"
STATIC Can * const can_insts[] = CAN_INSTS;
STATIC canio_can_obj_t *can_objs[MP_ARRAY_SIZE(can_insts)];
// This must be placed in the first 64kB of RAM
STATIC COMPILER_SECTION(".canram") canio_can_state_t can_state[MP_ARRAY_SIZE(can_insts)];
__attribute__((optimize("O0"), noinline))
void common_hal_canio_can_construct(canio_can_obj_t *self, mcu_pin_obj_t *rx, mcu_pin_obj_t *tx, int baudrate, bool loopback, bool silent)
{
mcu_pin_function_t *tx_function = mcu_find_pin_function(can_tx, tx, -1, MP_QSTR_tx);
int instance = tx_function->instance;
mcu_pin_function_t *rx_function = mcu_find_pin_function(can_rx, rx, instance, MP_QSTR_rx);
const uint32_t can_frequency = CONF_CAN0_FREQUENCY;
#define DIV_ROUND(a, b) (((a) + (b)/2) / (b))
#define DIV_ROUND_UP(a, b) (((a) + (b) - 1) / (b))
uint32_t clocks_per_bit = DIV_ROUND(can_frequency, baudrate);
uint32_t clocks_to_sample = DIV_ROUND(clocks_per_bit * 7, 8);
uint32_t clocks_after_sample = clocks_per_bit - clocks_to_sample;
uint32_t divisor = MAX(DIV_ROUND_UP(clocks_to_sample, 256), DIV_ROUND_UP(clocks_after_sample, 128));
if (divisor > 32) {
mp_raise_OSError(MP_EINVAL); // baudrate cannot be attained (16kHz or something is lower bound, should never happen)
}
gpio_set_pin_direction(tx_function->pin, GPIO_DIRECTION_OUT);
gpio_set_pin_function(tx_function->pin, tx_function->function);
common_hal_never_reset_pin(tx_function->obj);
if (rx_function) {
gpio_set_pin_direction(rx_function->pin, GPIO_DIRECTION_IN);
gpio_set_pin_function(rx_function->pin, rx_function->function);
common_hal_never_reset_pin(rx_function->obj);
}
self->tx_pin_number = common_hal_mcu_pin_number(tx);
self->rx_pin_number = rx ? common_hal_mcu_pin_number(rx) : COMMON_HAL_MCU_NO_PIN;
self->hw = can_insts[instance];
self->state = &can_state[instance];
self->loopback = loopback;
// Allow configuration change
hri_can_set_CCCR_INIT_bit(self->hw);
while (hri_can_get_CCCR_INIT_bit(self->hw) == 0) {
}
hri_can_set_CCCR_CCE_bit(self->hw);
if(instance == 0) {
hri_mclk_set_AHBMASK_CAN0_bit(MCLK);
hri_gclk_write_PCHCTRL_reg(GCLK, CAN0_GCLK_ID, CONF_GCLK_CAN0_SRC | (1 << GCLK_PCHCTRL_CHEN_Pos));
NVIC_DisableIRQ(CAN0_IRQn);
NVIC_ClearPendingIRQ(CAN0_IRQn);
NVIC_EnableIRQ(CAN0_IRQn);
hri_can_write_ILE_reg(self->hw, CAN_ILE_EINT0);
#ifdef CAN1_GCLK_ID
} else if(instance == 1) {
hri_mclk_set_AHBMASK_CAN1_bit(MCLK);
hri_gclk_write_PCHCTRL_reg(GCLK, CAN1_GCLK_ID, CONF_GCLK_CAN1_SRC | (1 << GCLK_PCHCTRL_CHEN_Pos));
NVIC_DisableIRQ(CAN1_IRQn);
NVIC_ClearPendingIRQ(CAN1_IRQn);
NVIC_EnableIRQ(CAN1_IRQn);
hri_can_write_ILE_reg(self->hw, CAN_ILE_EINT0);
#endif
}
self->hw->CCCR.bit.FDOE = 0; // neither FD nor Bit Rate Switch enabled
self->hw->CCCR.bit.BRSE = 0;
hri_can_write_MRCFG_reg(self->hw, CAN_MRCFG_QOS(CAN_MRCFG_QOS_DISABLE_Val)); // QoS disabled (no sensitive operation)
// A "nominal bit" is a header bit. With dual rate CAN FD, this is a slower rate
{
CAN_NBTP_Type btp = {
// 0 means "1 tq", but 2 is subtracted from NTSEG1 for the
// fixed 1 "SYNC" tq
.bit.NTSEG1 = DIV_ROUND(clocks_to_sample, divisor) - 2,
.bit.NTSEG2 = DIV_ROUND(clocks_after_sample, divisor) - 1,
.bit.NBRP = divisor - 1,
.bit.NSJW = DIV_ROUND(clocks_after_sample, divisor * 4),
};
hri_can_write_NBTP_reg(self->hw, btp.reg);
}
// we don't do the high bit rate yet, so do we need to set this register?
// hri_can_write_DBTP_reg(self->hw, ???);
// A "data bit" is a data bit :) with dul rate CAN FD, this is a higher
// rate. However, CAN FD is not implemented in CircuitPython, and this is the same rate as
// the "nominal rate".
{
CAN_DBTP_Type btp = {
.bit.DTSEG1 = DIV_ROUND(clocks_to_sample, divisor) - 1,
.bit.DTSEG2 = DIV_ROUND(clocks_after_sample, divisor) - 1,
.bit.DBRP = divisor - 1,
.bit.DSJW = DIV_ROUND(clocks_after_sample, divisor * 4),
};
hri_can_write_DBTP_reg(self->hw, btp.reg);
}
{
CAN_RXF0C_Type rxf = {
.bit.F0SA = (uint32_t)self->state->rx0_fifo,
.bit.F0S = COMMON_HAL_CANIO_RX_FIFO_SIZE,
};
hri_can_write_RXF0C_reg(self->hw, rxf.reg);
}
{
CAN_RXF1C_Type rxf = {
.bit.F1SA = (uint32_t)self->state->rx1_fifo,
.bit.F1S = COMMON_HAL_CANIO_RX_FIFO_SIZE,
};
hri_can_write_RXF1C_reg(self->hw, rxf.reg);
}
// All RX data has an 8 byte payload (max)
{
CAN_RXESC_Type esc = {
.bit.F0DS = CAN_RXESC_F0DS_DATA8_Val,
.bit.F1DS = CAN_RXESC_F1DS_DATA8_Val,
.bit.RBDS = CAN_RXESC_RBDS_DATA8_Val,
};
hri_can_write_RXESC_reg(self->hw, esc.reg);
}
// All TX data has an 8 byte payload (max)
{
CAN_TXESC_Type esc = {
.bit.TBDS = CAN_TXESC_TBDS_DATA8_Val,
};
hri_can_write_TXESC_reg(self->hw, esc.reg);
}
{
CAN_TXBC_Type bc = {
.bit.TBSA = (uint32_t)self->state->tx_fifo,
.bit.NDTB = COMMON_HAL_CANIO_TX_FIFO_SIZE,
.bit.TFQM = 0, // Messages are transmitted in the order submitted
};
hri_can_write_TXBC_reg(self->hw, bc.reg);
}
{
CAN_TXEFC_Type efc = {
.bit.EFS = 0,
};
hri_can_write_TXEFC_reg(self->hw, efc.reg);
}
{
CAN_GFC_Type gfc = {
.bit.RRFE = 1,
.bit.ANFS = CAN_GFC_ANFS_RXF0_Val,
.bit.ANFE = CAN_GFC_ANFE_REJECT_Val,
};
hri_can_write_GFC_reg(self->hw, gfc.reg);
}
{
CAN_SIDFC_Type dfc = {
.bit.LSS = COMMON_HAL_CANIO_RX_FILTER_SIZE,
.bit.FLSSA = (uint32_t)self->state->rx_filter
};
hri_can_write_SIDFC_reg(self->hw, dfc.reg);
}
{
CAN_XIDFC_Type dfc = {
.bit.LSE = 0,
};
hri_can_write_XIDFC_reg(self->hw, dfc.reg);
}
hri_can_write_XIDAM_reg(self->hw, CAN_XIDAM_RESETVALUE);
// silent: The CAN is set in Bus Monitoring Mode by programming CCCR.MON to '1'. (tx pin unused)
// external loopback: The CAN can be set in External Loop Back Mode by programming TEST.LBCK and CCCR.MON to '1'. (rx pin unused)
// internal loopback (silent loopback): Internal Loop Back Mode is entered by programming bits TEST.LBCK and CCCR.MON to '1'. (tx, rx unused)
self->hw->CCCR.bit.MON = silent;
self->hw->CCCR.bit.TEST = loopback;
self->hw->TEST.bit.LBCK = loopback;
if(instance == 0) {
NVIC_DisableIRQ(CAN0_IRQn);
NVIC_ClearPendingIRQ(CAN0_IRQn);
NVIC_EnableIRQ(CAN0_IRQn);
#ifdef CAN1_GCLK_ID
} else if(instance == 1) {
NVIC_DisableIRQ(CAN1_IRQn);
NVIC_ClearPendingIRQ(CAN1_IRQn);
NVIC_EnableIRQ(CAN1_IRQn);
#endif
}
hri_can_write_ILE_reg(self->hw, CAN_ILE_EINT0);
// Prevent configuration change
hri_can_clear_CCCR_CCE_bit(self->hw);
hri_can_clear_CCCR_INIT_bit(self->hw);
while (hri_can_get_CCCR_INIT_bit(self->hw)) {
}
can_objs[instance] = self;
}
int common_hal_canio_can_loopback_get(canio_can_obj_t *self)
{
return self->loopback;
}
int common_hal_canio_can_baudrate_get(canio_can_obj_t *self)
{
return self->baudrate;
}
int common_hal_canio_can_transmit_error_count_get(canio_can_obj_t *self)
{
return -1;
}
int common_hal_canio_can_receive_error_count_get(canio_can_obj_t *self)
{
return -1;
}
int common_hal_canio_can_error_warning_state_count_get(canio_can_obj_t *self)
{
return -1;
}
int common_hal_canio_can_error_passive_state_count_get(canio_can_obj_t *self)
{
return -1;
}
int common_hal_canio_can_bus_off_state_count_get(canio_can_obj_t *self)
{
return -1;
}
int common_hal_canio_can_state_get(canio_can_obj_t *self) {
return -1;
}
void common_hal_canio_can_send(canio_can_obj_t *self, canio_message_obj_t *message)
{
// We have just one dedicated TX buffer, use it!
canio_can_fifo_t *ent = &self->state->tx_fifo[0];
ent->txb0.bit.ESI = false;
ent->txb0.bit.XTD = false;
ent->txb0.bit.RTR = message->rtr;
ent->txb0.bit.ID = message->id << 18; // short addresses are left-justified
ent->txb1.bit.MM = 0; // "message marker"
ent->txb1.bit.EFC = 0; // don't store fifo events to event queue
ent->txb1.bit.FDF = 0; // Classic CAN format
ent->txb1.bit.BRS = 0; // No bit rate switching
ent->txb1.bit.DLC = message->size;
if (!message->rtr) {
memcpy(ent->data, message->data, message->size);
}
// TX buffer add request
self->hw->TXBAR.reg = 1;
// wait 8ms (hard coded for now) for TX to occur
uint64_t deadline = port_get_raw_ticks(NULL) + 8;
while (port_get_raw_ticks(NULL) < deadline && !(self->hw->TXBTO.reg & 1)) {
RUN_BACKGROUND_TASKS;
}
}
bool common_hal_canio_can_deinited(canio_can_obj_t *self) {
return !self->hw;
}
void common_hal_canio_can_check_for_deinit(canio_can_obj_t *self) {
if(common_hal_canio_can_deinited(self)) {
raise_deinited_error();
}
}
void common_hal_canio_can_deinit(canio_can_obj_t *self)
{
if (self->hw) {
hri_can_set_CCCR_INIT_bit(self->hw);
self->hw = 0;
}
if (self->rx_pin_number != COMMON_HAL_MCU_NO_PIN) {
reset_pin_number(self->rx_pin_number);
self->rx_pin_number = COMMON_HAL_MCU_NO_PIN;
}
if (self->tx_pin_number != COMMON_HAL_MCU_NO_PIN) {
reset_pin_number(self->tx_pin_number);
self->tx_pin_number = COMMON_HAL_MCU_NO_PIN;
}
}
void common_hal_canio_reset(void) {
memset(can_state, 0, sizeof(can_state));
for (size_t i=0; i<MP_ARRAY_SIZE(can_insts); i++) {
hri_can_set_CCCR_INIT_bit(can_insts[i]);
}
for (size_t i=0; i<MP_ARRAY_SIZE(can_objs); i++) {
if (can_objs[i]) {
common_hal_canio_can_deinit(can_objs[i]);
can_objs[i] = NULL;
}
}
}
STATIC void can_handler(int i) {
canio_can_obj_t *self = can_objs[i];
(void) self;
Can *hw = can_insts[i];
uint32_t ir = hri_can_read_IR_reg(hw);
/* Handle various interrupts */
/* Acknowledge interrupt */
hri_can_write_IR_reg(hw, ir);
}
__attribute__((used))
void CAN0_Handler(void) {
can_handler(0);
}
#ifdef CAN1_GCLK_ID
__attribute__((used))
void CAN1_Handler(void) {
can_handler(1);
}
#endif

View File

@ -0,0 +1,62 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2020 Jeff Epler for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#pragma once
#include "py/obj.h"
#include "component/can.h"
#include "common-hal/microcontroller/Pin.h"
#include "common-hal/_canio/__init__.h"
#include "shared-module/_canio/Message.h"
#define COMMON_HAL_CAN_RX_FIFO_LEN (2)
#define COMMON_HAL_CAN_TX_FIFO_LEN (2)
typedef struct {
mp_obj_base_t base;
Can *hw;
int baudrate;
uint8_t rx_pin_number, tx_pin_number;
bool loopback;
bool silent;
canio_can_state_t *state;
bool fifo0_in_use:1;
bool fifo1_in_use:1;
} canio_can_obj_t;
void common_hal_canio_can_construct(canio_can_obj_t *self, mcu_pin_obj_t *rx, mcu_pin_obj_t *tx, int baudrate, bool loopback, bool silent);
int common_hal_canio_can_state_get(canio_can_obj_t *self);
int common_hal_canio_can_baudrate_get(canio_can_obj_t *self);
int common_hal_canio_can_transmit_error_count_get(canio_can_obj_t *self);
int common_hal_canio_can_receive_error_count_get(canio_can_obj_t *self);
int common_hal_canio_can_error_warning_state_count_get(canio_can_obj_t *self);
int common_hal_canio_can_error_passive_state_count_get(canio_can_obj_t *self);
int common_hal_canio_can_bus_off_state_count_get(canio_can_obj_t *self);
void common_hal_canio_can_send(canio_can_obj_t *self, canio_message_obj_t *message);
void common_hal_canio_can_deinit(canio_can_obj_t *self);
void common_hal_canio_can_check_for_deinit(canio_can_obj_t *self);
bool common_hal_canio_can_deinited(canio_can_obj_t *self);
void common_hal_canio_reset(void);

View File

@ -0,0 +1,117 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2020 Jeff Epler for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <math.h>
#include <string.h>
#include "py/obj.h"
#include "py/runtime.h"
#include "common-hal/_canio/__init__.h"
#include "common-hal/_canio/Listener.h"
#include "shared-bindings/util.h"
#include "supervisor/shared/tick.h"
void common_hal_canio_listener_construct(canio_listener_obj_t *self, canio_can_obj_t *can, size_t nmatch, canio_match_obj_t **matches, float timeout) {
if (nmatch) {
mp_raise_NotImplementedError(NULL);
}
if (!can->fifo0_in_use) {
self->fifo_idx = 0;
self->fifo = can->state->rx0_fifo;
self->hw = (canio_rxfifo_reg_t*)&can->hw->RXF0C;
can->hw->IR.reg = CAN_IR_RF0N | CAN_IR_RF0W | CAN_IR_RF0F | CAN_IR_RF0L;
can->fifo0_in_use = true;
} else if (!can->fifo1_in_use) {
self->fifo_idx = 1;
self->fifo = can->state->rx1_fifo;
self->hw = (canio_rxfifo_reg_t*)&can->hw->RXF1C;
can->fifo1_in_use = true;
can->hw->IR.reg = CAN_IR_RF1N | CAN_IR_RF1W | CAN_IR_RF1F | CAN_IR_RF1L;
} else {
mp_raise_ValueError(translate("All RX FIFOs in use"));
}
self->can = can;
common_hal_canio_listener_set_timeout(self, timeout);
}
void common_hal_canio_listener_set_timeout(canio_listener_obj_t *self, float timeout) {
self->timeout_ms = (int)MICROPY_FLOAT_C_FUN(ceil)(timeout * 1000);
}
float common_hal_canio_listener_get_timeout(canio_listener_obj_t *self) {
return self->timeout_ms / 1000.0f;
}
void common_hal_canio_listener_check_for_deinit(canio_listener_obj_t *self) {
if(!self->can) {
raise_deinited_error();
}
common_hal_canio_can_check_for_deinit(self->can);
}
int common_hal_canio_listener_in_waiting(canio_listener_obj_t *self) {
return self->hw->RXFS.bit.F0FL;
}
bool common_hal_canio_listener_readinto(canio_listener_obj_t *self, canio_message_obj_t *message) {
if (!common_hal_canio_listener_in_waiting(self)) {
uint64_t deadline = supervisor_ticks_ms64() + self->timeout_ms;
do {
if(supervisor_ticks_ms64() > deadline) {
return false;
}
} while (!common_hal_canio_listener_in_waiting(self));
}
int index = self->hw->RXFS.bit.F0GI;
canio_can_fifo_t *hw_message = &self->fifo[index];
message->id = hw_message->rxb0.bit.ID >> 18; // short addresses are left-justified
message->rtr = hw_message->rxb0.bit.RTR;
message->size = hw_message->rxb1.bit.DLC;
if(!message->rtr) {
memcpy(message->data, hw_message->data, message->size);
}
self->hw->RXFA.bit.F0AI = index;
return true;
}
void common_hal_canio_listener_deinit(canio_listener_obj_t *self) {
// free our FIFO, clear our matches, SOMETHING
if(self->can) {
if(self->fifo_idx == 0) {
self->can->fifo0_in_use = false;
}
if(self->fifo_idx == 1) {
self->can->fifo1_in_use = false;
}
}
self->fifo_idx = -1;
self->fifo = NULL;
self->can = NULL;
self->hw = NULL;
}

View File

@ -0,0 +1,53 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2020 Jeff Epler for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#pragma once
#include "common-hal/_canio/CAN.h"
#include "shared-module/_canio/Match.h"
typedef struct {
__IO CAN_RXF0C_Type RXFC; /**< \brief (R/W 32) Rx FIFO n Configuration */
__I CAN_RXF0S_Type RXFS; /**< \brief (R/ 32) Rx FIFO n Status */
__IO CAN_RXF0A_Type RXFA; /**< \brief (R/W 32) Rx FIFO n Acknowledge */
} canio_rxfifo_reg_t;
typedef struct {
mp_obj_base_t base;
canio_can_obj_t *can;
canio_can_fifo_t *fifo;
canio_rxfifo_reg_t *hw;
uint32_t timeout_ms;
uint8_t fifo_idx;
} canio_listener_obj_t;
void common_hal_canio_listener_construct(canio_listener_obj_t *self, canio_can_obj_t *can, size_t nmatch, canio_match_obj_t **matches, float timeout);
void common_hal_canio_listener_check_for_deinit(canio_listener_obj_t *self);
void common_hal_canio_listener_deinit(canio_listener_obj_t *self);
bool common_hal_canio_listener_readinto(canio_listener_obj_t *self, canio_message_obj_t *message);
int common_hal_canio_listener_in_waiting(canio_listener_obj_t *self);
float common_hal_canio_listener_get_timeout(canio_listener_obj_t *self);
void common_hal_canio_listener_set_timeout(canio_listener_obj_t *self, float timeout);

View File

@ -0,0 +1,25 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2020 Jeff Epler for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/

View File

@ -0,0 +1,62 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2020 Jeff Epler for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#pragma once
#include "hal/utils/include/utils.h"
#include "component/can.h"
#define COMMON_HAL_CANIO_MAX_MESSAGE_LENGTH (8)
#define COMMON_HAL_CANIO_RX_FIFO_SIZE (3)
#define COMMON_HAL_CANIO_RX_FILTER_SIZE (4)
#define COMMON_HAL_CANIO_TX_FIFO_SIZE (1)
typedef struct canio_listener canio_listener_t;
typedef struct canio_can canio_can_t;
typedef struct {
union {
CAN_RXBE_0_Type rxb0;
CAN_TXBE_0_Type txb0;
CAN_RXF0E_0_Type rxf0;
};
union {
CAN_RXBE_1_Type rxb1;
CAN_TXBE_1_Type txb1;
CAN_RXF0E_1_Type rxf1;
};
COMPILER_ALIGNED(4)
uint8_t data[COMMON_HAL_CANIO_MAX_MESSAGE_LENGTH];
} canio_can_fifo_t;
typedef uint32_t canio_can_filter_t;
typedef struct {
canio_can_fifo_t tx_fifo[COMMON_HAL_CANIO_TX_FIFO_SIZE];
canio_can_fifo_t rx0_fifo[COMMON_HAL_CANIO_RX_FIFO_SIZE];
canio_can_fifo_t rx1_fifo[COMMON_HAL_CANIO_RX_FIFO_SIZE];
canio_can_filter_t rx_filter[COMMON_HAL_CANIO_RX_FILTER_SIZE];
} canio_can_state_t;

View File

@ -0,0 +1,31 @@
#!/usr/bin/python3
def defines(name, suffix):
print(f'mcu_pin_function_t {name} [] = {{')
for instance in (0, 1):
for function in 'HI':
for port in 'ABCD':
for idx in range(32):
pin = f'P{port}{idx:02d}'
pinmux = f'PINMUX_{pin}{function}_CAN{instance}_{suffix}'
print(f'''\
#if defined({pinmux}) && ! defined(IGNORE_PIN_{pin})
{{&pin_{pin}, {instance}, PIN_{pin}, {pinmux} & 0xffff}},
#endif''')
print(f'{{NULL, 0, 0}}')
print(f'}};')
print()
print('''\
#include <stdint.h>
#include "py/obj.h"
#include "sam.h"
#include "samd/pins.h"
#include "mpconfigport.h"
#include "atmel_start_pins.h"
#include "hal/include/hal_gpio.h"
#include "common-hal/microcontroller/Pin.h"
''')
defines('can_rx', 'RX')
defines('can_tx', 'TX')

View File

@ -142,6 +142,9 @@ endif
ifeq ($(CIRCUITPY_CAMERA),1) ifeq ($(CIRCUITPY_CAMERA),1)
SRC_PATTERNS += camera/% SRC_PATTERNS += camera/%
endif endif
ifeq ($(CIRCUITPY_CANIO),1)
SRC_PATTERNS += _canio/%
endif
ifeq ($(CIRCUITPY_COUNTIO),1) ifeq ($(CIRCUITPY_COUNTIO),1)
SRC_PATTERNS += countio/% SRC_PATTERNS += countio/%
endif endif
@ -315,6 +318,9 @@ SRC_COMMON_HAL_ALL = \
busio/__init__.c \ busio/__init__.c \
camera/__init__.c \ camera/__init__.c \
camera/Camera.c \ camera/Camera.c \
_canio/CAN.c \
_canio/Listener.c \
_canio/__init__.c \
countio/Counter.c \ countio/Counter.c \
countio/__init__.c \ countio/__init__.c \
digitalio/DigitalInOut.c \ digitalio/DigitalInOut.c \
@ -384,6 +390,7 @@ $(filter $(SRC_PATTERNS), \
_bleio/Address.c \ _bleio/Address.c \
_bleio/Attribute.c \ _bleio/Attribute.c \
_bleio/ScanEntry.c \ _bleio/ScanEntry.c \
_canio/Match.c \
_eve/__init__.c \ _eve/__init__.c \
camera/ImageFormat.c \ camera/ImageFormat.c \
digitalio/Direction.c \ digitalio/Direction.c \
@ -402,6 +409,8 @@ SRC_SHARED_MODULE_ALL = \
_bleio/Attribute.c \ _bleio/Attribute.c \
_bleio/ScanEntry.c \ _bleio/ScanEntry.c \
_bleio/ScanResults.c \ _bleio/ScanResults.c \
_canio/Match.c \
_canio/Message.c \
_eve/__init__.c \ _eve/__init__.c \
_pixelbuf/PixelBuf.c \ _pixelbuf/PixelBuf.c \
_pixelbuf/__init__.c \ _pixelbuf/__init__.c \

View File

@ -336,6 +336,13 @@ extern const struct _mp_obj_module_t camera_module;
#define CAMERA_MODULE #define CAMERA_MODULE
#endif #endif
#if CIRCUITPY_CANIO
extern const struct _mp_obj_module_t canio_module;
#define CANIO_MODULE { MP_OBJ_NEW_QSTR(MP_QSTR__canio), (mp_obj_t)&canio_module },
#else
#define CANIO_MODULE
#endif
#if CIRCUITPY_COUNTIO #if CIRCUITPY_COUNTIO
extern const struct _mp_obj_module_t countio_module; extern const struct _mp_obj_module_t countio_module;
#define COUNTIO_MODULE { MP_OBJ_NEW_QSTR(MP_QSTR_countio), (mp_obj_t)&countio_module }, #define COUNTIO_MODULE { MP_OBJ_NEW_QSTR(MP_QSTR_countio), (mp_obj_t)&countio_module },
@ -766,6 +773,7 @@ extern const struct _mp_obj_module_t wifi_module;
BOARD_MODULE \ BOARD_MODULE \
BUSIO_MODULE \ BUSIO_MODULE \
CAMERA_MODULE \ CAMERA_MODULE \
CANIO_MODULE \
COUNTIO_MODULE \ COUNTIO_MODULE \
DIGITALIO_MODULE \ DIGITALIO_MODULE \
DISPLAYIO_MODULE \ DISPLAYIO_MODULE \

View File

@ -93,6 +93,9 @@ CFLAGS += -DCIRCUITPY_BUSIO=$(CIRCUITPY_BUSIO)
CIRCUITPY_CAMERA ?= 0 CIRCUITPY_CAMERA ?= 0
CFLAGS += -DCIRCUITPY_CAMERA=$(CIRCUITPY_CAMERA) CFLAGS += -DCIRCUITPY_CAMERA=$(CIRCUITPY_CAMERA)
CIRCUITPY_CANIO ?= 0
CFLAGS += -DCIRCUITPY_CANIO=$(CIRCUITPY_CANIO)
CIRCUITPY_DIGITALIO ?= 1 CIRCUITPY_DIGITALIO ?= 1
CFLAGS += -DCIRCUITPY_DIGITALIO=$(CIRCUITPY_DIGITALIO) CFLAGS += -DCIRCUITPY_DIGITALIO=$(CIRCUITPY_DIGITALIO)

View File

@ -0,0 +1,338 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2020 Jeff Epler for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "common-hal/_canio/CAN.h"
#include "common-hal/_canio/Listener.h"
#include "shared-bindings/_canio/CAN.h"
#include "shared-bindings/_canio/Listener.h"
#include "shared-bindings/_canio/Match.h"
#include "shared-bindings/_canio/Message.h"
#include "shared-bindings/microcontroller/Pin.h"
#include "py/objproperty.h"
#include "py/runtime.h"
//|
//| class CAN:
//| """CAN bus protocol"""
//|
//| def __init__(self,
//| rx: microcontroller.Pin,
//| tx: Optional[microcontroller.Pin]=None,
//| *,
//| baudrate: int = 250000,
//| loopback: bool = False,
//| ):
//| """A common shared-bus protocol. The rx and tx pins are generally
//| connected to a transceiver which controls the H and L pins on a shared
//| bus.
//|
//| :param ~microcontrller.Pin rx: the pin to receive with.
//| :param ~microcontrller.Pin tx: the pin to transmit with, or None if the peripheral should operate in "silent" mode.
//| :param int baudrate: The bit rate of the bus in Hz. All devices on the bus must agree on this value.
//| :param bool loopback: True if the peripheral will be operated in loopback mode.
//| """
//| ...
//|
//## auto_restart: bool = False, # Whether to restart communications after entering bus-off state
//## sample_point: float = .875, # When to sample within bit time (0.0-1.0)
STATIC mp_obj_t canio_can_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_rx, ARG_tx, ARG_baudrate, ARG_loopback, ARG_silent, NUM_ARGS };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_rx, MP_ARG_OBJ | MP_ARG_REQUIRED, {.u_obj = 0} },
{ MP_QSTR_tx, MP_ARG_OBJ, {.u_obj = 0} },
{ MP_QSTR_baudrate, MP_ARG_INT, {.u_int = 250000} },
{ MP_QSTR_loopback, MP_ARG_BOOL, {.u_bool = false} },
{ MP_QSTR_silent, MP_ARG_BOOL, {.u_bool = false} },
};
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
MP_STATIC_ASSERT( MP_ARRAY_SIZE(allowed_args) == NUM_ARGS );
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
mp_printf(&mp_plat_print, "ARG_rx=%d args[ARG_rx].u_obj=%p\n", ARG_rx, args[ARG_rx].u_obj);
mp_printf(&mp_plat_print, "ARG_tx=%d args[ARG_tx].u_obj=%p\n", ARG_tx, args[ARG_tx].u_obj);
mcu_pin_obj_t *rx_pin = validate_obj_is_free_pin(args[ARG_rx].u_obj);
mp_printf(&mp_plat_print, "rx_pin=%p\n", rx_pin);
mcu_pin_obj_t *tx_pin = validate_obj_is_free_pin_or_none(args[ARG_tx].u_obj);
mp_printf(&mp_plat_print, "tx_pin=%p\n", tx_pin);
canio_can_obj_t *self = m_new_obj(canio_can_obj_t);
self->base.type = &canio_can_type;
common_hal_canio_can_construct(self, rx_pin, tx_pin, args[ARG_baudrate].u_int, args[ARG_loopback].u_bool, args[ARG_silent].u_bool);
return MP_OBJ_FROM_PTR(self);
}
//| baudrate: int
//| """The baud rate(read-only)"""
//|
STATIC mp_obj_t canio_can_baudrate_get(mp_obj_t self_in) {
canio_can_obj_t *self = MP_OBJ_TO_PTR(self_in);
common_hal_canio_can_check_for_deinit(self);
return MP_OBJ_NEW_SMALL_INT(common_hal_canio_can_baudrate_get(self));
}
MP_DEFINE_CONST_FUN_OBJ_1(canio_can_baudrate_get_obj, canio_can_baudrate_get);
STATIC const mp_obj_property_t canio_can_baudrate_obj = {
.base.type = &mp_type_property,
.proxy = {(mp_obj_t)&canio_can_baudrate_get_obj,
(mp_obj_t)mp_const_none,
(mp_obj_t)mp_const_none},
};
//| state: State
//| """The status of the hardware (read-only)"""
//|
STATIC mp_obj_t canio_can_state_get(mp_obj_t self_in) {
canio_can_obj_t *self = MP_OBJ_TO_PTR(self_in);
common_hal_canio_can_check_for_deinit(self);
return MP_OBJ_NEW_SMALL_INT(common_hal_canio_can_state_get(self));
}
MP_DEFINE_CONST_FUN_OBJ_1(canio_can_state_get_obj, canio_can_state_get);
STATIC const mp_obj_property_t canio_can_state_obj = {
.base.type = &mp_type_property,
.proxy = {(mp_obj_t)&canio_can_state_get_obj,
(mp_obj_t)mp_const_none,
(mp_obj_t)mp_const_none},
};
//| transmit_error_count: int
//| """The number of transmit errors (read-only). Increased for a detected transmission error, decreased for successful transmission. Limited to the range from 0 to 255 inclusive. Also called TEC."""
//|
STATIC mp_obj_t canio_can_transmit_error_count_get(mp_obj_t self_in) {
canio_can_obj_t *self = MP_OBJ_TO_PTR(self_in);
common_hal_canio_can_check_for_deinit(self);
return MP_OBJ_NEW_SMALL_INT(common_hal_canio_can_transmit_error_count_get(self));
}
MP_DEFINE_CONST_FUN_OBJ_1(canio_can_transmit_error_count_get_obj, canio_can_transmit_error_count_get);
STATIC const mp_obj_property_t canio_can_transmit_error_count_obj = {
.base.type = &mp_type_property,
.proxy = {(mp_obj_t)&canio_can_transmit_error_count_get_obj,
(mp_obj_t)mp_const_none,
(mp_obj_t)mp_const_none},
};
//| receive_error_count: int
//| """The number of receive errors (read-only). Increased for a detected reception error, decreased for successful reception. Limited to the range from 0 to 255 inclusive. Also called REC."""
//|
STATIC mp_obj_t canio_can_receive_error_count_get(mp_obj_t self_in) {
canio_can_obj_t *self = MP_OBJ_TO_PTR(self_in);
common_hal_canio_can_check_for_deinit(self);
return MP_OBJ_NEW_SMALL_INT(common_hal_canio_can_receive_error_count_get(self));
}
MP_DEFINE_CONST_FUN_OBJ_1(canio_can_receive_error_count_get_obj, canio_can_receive_error_count_get);
STATIC const mp_obj_property_t canio_can_receive_error_count_obj = {
.base.type = &mp_type_property,
.proxy = {(mp_obj_t)&canio_can_receive_error_count_get_obj,
(mp_obj_t)mp_const_none,
(mp_obj_t)mp_const_none},
};
//| error_warning_state_count: int
//| """The number of times the controller enterted the Error Warning state (read-only). This number wraps around to 0 after an implementation-defined number of errors."""
//|
STATIC mp_obj_t canio_can_error_warning_state_count_get(mp_obj_t self_in) {
canio_can_obj_t *self = MP_OBJ_TO_PTR(self_in);
common_hal_canio_can_check_for_deinit(self);
return MP_OBJ_NEW_SMALL_INT(common_hal_canio_can_error_warning_state_count_get(self));
}
MP_DEFINE_CONST_FUN_OBJ_1(canio_can_error_warning_state_count_get_obj, canio_can_error_warning_state_count_get);
STATIC const mp_obj_property_t canio_can_error_warning_state_count_obj = {
.base.type = &mp_type_property,
.proxy = {(mp_obj_t)&canio_can_error_warning_state_count_get_obj,
(mp_obj_t)mp_const_none,
(mp_obj_t)mp_const_none},
};
//| error_passive_state_count: int
//| """The number of times the controller enterted the Error Passive state (read-only). This number wraps around to 0 after an implementation-defined number of errors."""
//|
STATIC mp_obj_t canio_can_error_passive_state_count_get(mp_obj_t self_in) {
canio_can_obj_t *self = MP_OBJ_TO_PTR(self_in);
common_hal_canio_can_check_for_deinit(self);
return MP_OBJ_NEW_SMALL_INT(common_hal_canio_can_error_passive_state_count_get(self));
}
MP_DEFINE_CONST_FUN_OBJ_1(canio_can_error_passive_state_count_get_obj, canio_can_error_passive_state_count_get);
STATIC const mp_obj_property_t canio_can_error_passive_state_count_obj = {
.base.type = &mp_type_property,
.proxy = {(mp_obj_t)&canio_can_error_passive_state_count_get_obj,
(mp_obj_t)mp_const_none,
(mp_obj_t)mp_const_none},
};
//| bus_off_state_count: int
//| """The number of times the controller enterted the Bus Off state (read-only). This number wraps around to 0 after an implementation-defined number of errors."""
//|
STATIC mp_obj_t canio_can_bus_off_state_count_get(mp_obj_t self_in) {
canio_can_obj_t *self = MP_OBJ_TO_PTR(self_in);
common_hal_canio_can_check_for_deinit(self);
return MP_OBJ_NEW_SMALL_INT(common_hal_canio_can_bus_off_state_count_get(self));
}
MP_DEFINE_CONST_FUN_OBJ_1(canio_can_bus_off_state_count_get_obj, canio_can_bus_off_state_count_get);
STATIC const mp_obj_property_t canio_can_bus_off_state_count_obj = {
.base.type = &mp_type_property,
.proxy = {(mp_obj_t)&canio_can_bus_off_state_count_get_obj,
(mp_obj_t)mp_const_none,
(mp_obj_t)mp_const_none},
};
#if 0
//| # pending_tx_count: int
//| # """The number of messages waiting to be transmitted. (read-only)"""
#endif
//| def listen(filters: Optional[Sequence[Filter]]=None, *, timeout: float=10) -> Listener:
//| """Start receiving messages that match any one of the filters.
//| Creating a listener is an expensive operation and can interfere with reception of messages by other listeners.
//| There is an implementation-defined maximum number of listeners and limit to the complexity of the filters.
//| If the hardware cannot support all the requested filters, a ValueError is raised. Note that generally there are some number of hardware filters shared among all fifos.
//| A message can be received by at most one Listener.
//| An empty filter list causes all messages to be accepted.
//| Timeout dictates how long readinto, read and next() will block.
//| Readinto will return false(), read will return None, and next() will raise StopIteration."""
//| ...
//|
STATIC mp_obj_t canio_can_listen(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
canio_can_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
common_hal_canio_can_check_for_deinit(self);
enum { ARG_match, ARG_timeout, NUM_ARGS };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_match, MP_ARG_OBJ, {.u_obj = 0} },
{ MP_QSTR_timeout, MP_ARG_OBJ, {.u_obj = 0} },
};
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
MP_STATIC_ASSERT( MP_ARRAY_SIZE(allowed_args) == NUM_ARGS );
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
size_t nmatch = 0;
mp_obj_t *match_objects = NULL;
if (args[ARG_match].u_obj) {
mp_obj_get_array(args[ARG_match].u_obj, &nmatch, &match_objects);
}
canio_match_obj_t *matches[nmatch];
for (size_t i=0; i<nmatch; i++) {
mp_obj_type_t *type = mp_obj_get_type(match_objects[i]);
if(type != &canio_match_type) {
mp_raise_TypeError_varg(translate("expected '%q' but got '%q'"), MP_QSTR_Match, type->name);
}
matches[i] = MP_OBJ_TO_PTR(match_objects[i]);
}
float timeout = args[ARG_timeout].u_obj ? mp_obj_get_float(args[ARG_timeout].u_obj) : 10.0f;
canio_listener_obj_t *listener = m_new_obj(canio_listener_obj_t);
listener->base.type = &canio_listener_type;
common_hal_canio_listener_construct(listener, self, nmatch, matches, timeout);
return listener;
}
MP_DEFINE_CONST_FUN_OBJ_KW(canio_can_listen_obj, 1, canio_can_listen);
//| def send(message: Message) -> None:
//| """Send a message on the bus with the given data and id.
//| If the message could not be sent due to a full fifo or a bus error condition, RuntimeError is raised.
//| """
//| ...
//|
STATIC mp_obj_t canio_can_send(mp_obj_t self_in, mp_obj_t message_in) {
canio_can_obj_t *self = MP_OBJ_TO_PTR(self_in);
common_hal_canio_can_check_for_deinit(self);
mp_obj_type_t *message_type = mp_obj_get_type(message_in);
if (message_type != &canio_message_type) {
mp_raise_TypeError_varg(translate("expected '%q' but got '%q'"), MP_QSTR_Message, message_type->name);
}
canio_message_obj_t *message = message_in;
common_hal_canio_can_send(self, message);
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_2(canio_can_send_obj, canio_can_send);
//| def deinit(self) -> None:
//| """Deinitialize this object, freeing its hardware resources"""
//| ...
//|
STATIC mp_obj_t canio_can_deinit(mp_obj_t self_in) {
canio_can_obj_t *self = MP_OBJ_TO_PTR(self_in);
common_hal_canio_can_deinit(self);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(canio_can_deinit_obj, canio_can_deinit);
//| def __enter__(self) -> CAN:
//| """Returns self, to allow the object to be used in a `with` statement for resource control"""
//| ...
//|
STATIC mp_obj_t canio_can_enter(mp_obj_t self_in) {
canio_can_obj_t *self = MP_OBJ_TO_PTR(self_in);
common_hal_canio_can_check_for_deinit(self);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(canio_can_enter_obj, canio_can_enter);
//| def __exit__(self, unused1, unused2, unused3) -> None:
//| """Calls deinit()"""
//| ...
STATIC mp_obj_t canio_can_exit(size_t num_args, const mp_obj_t args[]) {
canio_can_obj_t *self = MP_OBJ_TO_PTR(args[0]);
common_hal_canio_can_deinit(self);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(canio_can_exit_obj, 4, 4, canio_can_exit);
STATIC const mp_rom_map_elem_t canio_can_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&canio_can_enter_obj) },
{ MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&canio_can_exit_obj) },
{ MP_ROM_QSTR(MP_QSTR_bus_off_state_count), MP_ROM_PTR(&canio_can_bus_off_state_count_obj) },
{ MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&canio_can_deinit_obj) },
{ MP_ROM_QSTR(MP_QSTR_error_passive_state_count), MP_ROM_PTR(&canio_can_error_passive_state_count_obj) },
{ MP_ROM_QSTR(MP_QSTR_error_warning_state_count), MP_ROM_PTR(&canio_can_error_warning_state_count_obj) },
{ MP_ROM_QSTR(MP_QSTR_listen), MP_ROM_PTR(&canio_can_listen_obj) },
{ MP_ROM_QSTR(MP_QSTR_receive_error_count), MP_ROM_PTR(&canio_can_receive_error_count_obj) },
{ MP_ROM_QSTR(MP_QSTR_send), MP_ROM_PTR(&canio_can_send_obj) },
{ MP_ROM_QSTR(MP_QSTR_state), MP_ROM_PTR(&canio_can_state_obj) },
{ MP_ROM_QSTR(MP_QSTR_baudrate), MP_ROM_PTR(&canio_can_baudrate_obj) },
{ MP_ROM_QSTR(MP_QSTR_transmit_error_count), MP_ROM_PTR(&canio_can_transmit_error_count_obj) },
};
STATIC MP_DEFINE_CONST_DICT(canio_can_locals_dict, canio_can_locals_dict_table);
const mp_obj_type_t canio_can_type = {
{ &mp_type_type },
.name = MP_QSTR_CAN,
.make_new = canio_can_make_new,
.locals_dict = (mp_obj_t)&canio_can_locals_dict,
};

View File

@ -0,0 +1,31 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2020 Jeff Epler for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#pragma once
#include "py/obj.h"
extern const mp_obj_type_t canio_can_type;

View File

@ -0,0 +1,197 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2020 Jeff Epler for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "shared-bindings/_canio/Listener.h"
#include "shared-bindings/_canio/Message.h"
#include "common-hal/_canio/Listener.h"
#include "py/runtime.h"
#include "py/objproperty.h"
//| class Listener:
//| """Listens for CAN message
//|
//| _canio.Listener is not constructed directly, but instead by calling the
//| Listen method of a _canio.CAN object."""
//|
//| def read(self) -> Optional[Message]:
//| """Returns a message, after waiting up to self.timeout seconds
//|
//| If no message is received in time, None is returned. Otherwise,
//| a Message is returned."""
//| ...
//|
STATIC mp_obj_t canio_listener_read(mp_obj_t self_in) {
canio_listener_obj_t *self = MP_OBJ_TO_PTR(self_in);
common_hal_canio_listener_check_for_deinit(self);
canio_message_obj_t *message = m_new_obj(canio_message_obj_t);
self->base.type = &canio_message_type;
if (common_hal_canio_listener_readinto(self, message)) {
return message;
} else {
m_free(message); // message did not escape into vm
}
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(canio_listener_read_obj, canio_listener_read);
//| def readinto(self, message: Message) -> bool:
//| """Returns a message, after waiting up to self.timeout seconds
//|
//| Returns True (and modifies message) if a message was received,
//| False otherwise."""
//| ...
//|
STATIC mp_obj_t canio_listener_readinto(mp_obj_t self_in, mp_obj_t message) {
canio_listener_obj_t *self = MP_OBJ_TO_PTR(self_in);
mp_obj_type_t *type = mp_obj_get_type(message);
if (type != &canio_message_type) {
mp_raise_TypeError_varg(translate("expected '%q' but got '%q'"), MP_QSTR_Message, type->name);
}
common_hal_canio_listener_check_for_deinit(self);
return mp_obj_new_bool(common_hal_canio_listener_readinto(self, message));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(canio_listener_readinto_obj, canio_listener_readinto);
//| def in_waiting(self) -> int:
//| """Returns the number of messages waiting"""
//| ...
//|
STATIC mp_obj_t canio_listener_in_waiting(mp_obj_t self_in) {
canio_listener_obj_t *self = MP_OBJ_TO_PTR(self_in);
common_hal_canio_listener_check_for_deinit(self);
return MP_OBJ_NEW_SMALL_INT(common_hal_canio_listener_in_waiting(self));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(canio_listener_in_waiting_obj, canio_listener_in_waiting);
//| def __iter__(self):
//| """Returns self, unless the object is deinitialized"""
//| ...
//|
STATIC mp_obj_t canio_listener_iter(mp_obj_t self_in) {
canio_listener_obj_t *self = MP_OBJ_TO_PTR(self_in);
common_hal_canio_listener_check_for_deinit(self);
return self;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(canio_listener_iter_obj, canio_listener_iter);
//| def __next__(self):
//| """Returns the next waiting message, if one is available
//|
//| If the object is deinitialized, raises ValueError.
//|
//| If no message is waiting raises StopIteration"""
//| ...
//|
STATIC mp_obj_t canio_listener_next(mp_obj_t self_in) {
canio_listener_obj_t *self = MP_OBJ_TO_PTR(self_in);
common_hal_canio_listener_check_for_deinit(self);
if(common_hal_canio_listener_in_waiting(self)) {
return canio_listener_read(self_in);
}
return self;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(canio_listener_next_obj, canio_listener_next);
//| def deinit(self) -> None:
//| """Deinitialize this object, freeing its hardware resources"""
//| ...
//|
STATIC mp_obj_t canio_listener_deinit(mp_obj_t self_in) {
canio_listener_obj_t *self = MP_OBJ_TO_PTR(self_in);
common_hal_canio_listener_deinit(self);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(canio_listener_deinit_obj, canio_listener_deinit);
//| def __enter__(self) -> CAN:
//| """Returns self, to allow the object to be used in a `with` statement for resource control"""
//| ...
//|
STATIC mp_obj_t canio_listener_enter(mp_obj_t self_in) {
canio_listener_obj_t *self = MP_OBJ_TO_PTR(self_in);
common_hal_canio_listener_check_for_deinit(self);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(canio_listener_enter_obj, canio_listener_enter);
//| def __exit__(self, unused1, unused2, unused3) -> None:
//| """Calls deinit()"""
//| ...
STATIC mp_obj_t canio_listener_exit(size_t num_args, const mp_obj_t args[]) {
canio_listener_obj_t *self = MP_OBJ_TO_PTR(args[0]);
common_hal_canio_listener_deinit(self);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(canio_listener_exit_obj, 4, 4, canio_listener_exit);
//| timeout : float
STATIC mp_obj_t canio_listener_timeout_get(mp_obj_t self_in) {
canio_listener_obj_t *self = MP_OBJ_TO_PTR(self_in);
common_hal_canio_listener_check_for_deinit(self);
return mp_obj_new_float(common_hal_canio_listener_get_timeout(self));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(canio_listener_timeout_get_obj, canio_listener_timeout_get);
STATIC mp_obj_t canio_listener_timeout_set(mp_obj_t self_in, mp_obj_t timeout_in) {
canio_listener_obj_t *self = MP_OBJ_TO_PTR(self_in);
common_hal_canio_listener_check_for_deinit(self);
common_hal_canio_listener_set_timeout(self, mp_obj_get_float(timeout_in));
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(canio_listener_timeout_set_obj, canio_listener_timeout_set);
STATIC const mp_obj_property_t canio_listener_timeout_obj = {
.base.type = &mp_type_property,
.proxy = {(mp_obj_t)&canio_listener_timeout_get_obj,
(mp_obj_t)&canio_listener_timeout_set_obj,
(mp_obj_t)mp_const_none},
};
STATIC const mp_rom_map_elem_t canio_listener_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&canio_listener_enter_obj) },
{ MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&canio_listener_exit_obj) },
{ MP_ROM_QSTR(MP_QSTR___iter__), MP_ROM_PTR(&canio_listener_iter_obj) },
{ MP_ROM_QSTR(MP_QSTR___next__), MP_ROM_PTR(&canio_listener_next_obj) },
{ MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&canio_listener_deinit_obj) },
{ MP_ROM_QSTR(MP_QSTR_in_waiting), MP_ROM_PTR(&canio_listener_in_waiting_obj) },
{ MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&canio_listener_read_obj) },
{ MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&canio_listener_readinto_obj) },
{ MP_ROM_QSTR(MP_QSTR_timeout), MP_ROM_PTR(&canio_listener_timeout_obj) },
};
STATIC MP_DEFINE_CONST_DICT(canio_listener_locals_dict, canio_listener_locals_dict_table);
const mp_obj_type_t canio_listener_type = {
{ &mp_type_type },
.name = MP_QSTR_Listener,
.locals_dict = (mp_obj_dict_t*)&canio_listener_locals_dict,
};

View File

@ -0,0 +1,31 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2020 Jeff Epler for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#pragma once
#include "py/obj.h"
extern const mp_obj_type_t canio_listener_type;

View File

@ -0,0 +1,140 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2020 Jeff Epler for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "shared-bindings/_canio/Match.h"
#include "shared-module/_canio/Match.h"
#include "py/objproperty.h"
#include "py/runtime.h"
//| class Match:
//| """Describe CAN bus messages to match"""
//|
//|
//| def __init__(self, address: int, *, mask: int = 0, extended: bool = False):
//| """Construct a Match with the given properties.
//|
//| If mask is nonzero, then the filter is for any sender which matches all
//| the nonzero bits in mask. Otherwise, it matches exactly the given address.
//| If extended is true then only extended addresses are matched, otherwise
//| only standard addresses are matched."""
//|
STATIC mp_obj_t canio_match_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_address, ARG_mask, ARG_extended, NUM_ARGS };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_address, MP_ARG_INT | MP_ARG_REQUIRED, {.u_int = 0} },
{ MP_QSTR_mask, MP_ARG_INT, {.u_int = 0} },
{ MP_QSTR_extended, MP_ARG_BOOL, {.u_bool = false} },
};
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
MP_STATIC_ASSERT( MP_ARRAY_SIZE(allowed_args) == NUM_ARGS );
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
int address_bits = args[ARG_extended].u_bool ? 0x1fffffff : 0x7ff;
int address = args[ARG_address].u_int;
int mask = args[ARG_mask].u_int;
if(address & ~address_bits) {
mp_raise_ValueError_varg(translate("%q out of range"), MP_QSTR_address);
}
if(mask & ~address_bits) {
mp_raise_ValueError_varg(translate("%q out of range"), MP_QSTR_mask);
}
canio_match_obj_t *self = m_new_obj(canio_match_obj_t);
self->base.type = &canio_match_type;
common_hal_canio_match_construct(self, args[ARG_address].u_int, args[ARG_mask].u_int, args[ARG_extended].u_bool);
return self;
}
//| address: int
//| """The address to match"""
//|
STATIC mp_obj_t canio_match_address_get(mp_obj_t self_in) {
canio_match_obj_t *self = self_in;
return MP_OBJ_NEW_SMALL_INT(common_hal_canio_match_address_get(self));
}
MP_DEFINE_CONST_FUN_OBJ_1(canio_match_address_get_obj, canio_match_address_get);
const mp_obj_property_t canio_match_address_obj = {
.base.type = &mp_type_property,
.proxy = {(mp_obj_t)&canio_match_address_get_obj,
(mp_obj_t)&mp_const_none_obj,
(mp_obj_t)&mp_const_none_obj},
};
//|
//| mask: int
//| """The optional mask of addresses to match"""
//|
STATIC mp_obj_t canio_match_mask_get(mp_obj_t self_in) {
canio_match_obj_t *self = self_in;
return MP_OBJ_NEW_SMALL_INT(common_hal_canio_match_mask_get(self));
}
MP_DEFINE_CONST_FUN_OBJ_1(canio_match_mask_get_obj, canio_match_mask_get);
const mp_obj_property_t canio_match_mask_obj = {
.base.type = &mp_type_property,
.proxy = {(mp_obj_t)&canio_match_mask_get_obj,
(mp_obj_t)&mp_const_none_obj,
(mp_obj_t)&mp_const_none_obj},
};
//| extended: bool
//| """True to match extended addresses, False to match standard addresses"""
//|
STATIC mp_obj_t canio_match_extended_get(mp_obj_t self_in) {
canio_match_obj_t *self = self_in;
return mp_obj_new_bool(common_hal_canio_match_extended_get(self));
}
MP_DEFINE_CONST_FUN_OBJ_1(canio_match_extended_get_obj, canio_match_extended_get);
const mp_obj_property_t canio_match_extended_obj = {
.base.type = &mp_type_property,
.proxy = {(mp_obj_t)&canio_match_extended_get_obj,
(mp_obj_t)&mp_const_none_obj,
(mp_obj_t)&mp_const_none_obj},
};
STATIC const mp_rom_map_elem_t canio_match_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_address), MP_ROM_PTR(&canio_match_address_obj) },
{ MP_ROM_QSTR(MP_QSTR_mask), MP_ROM_PTR(&canio_match_mask_obj) },
{ MP_ROM_QSTR(MP_QSTR_extended), MP_ROM_PTR(&canio_match_extended_obj) },
};
STATIC MP_DEFINE_CONST_DICT(canio_match_locals_dict, canio_match_locals_dict_table);
const mp_obj_type_t canio_match_type = {
{ &mp_type_type },
.name = MP_QSTR_Match,
.make_new = canio_match_make_new,
.locals_dict = (mp_obj_dict_t*)&canio_match_locals_dict,
};

View File

@ -0,0 +1,33 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2020 Jeff Epler for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#pragma once
#include "py/obj.h"
extern const mp_obj_type_t canio_match_type;
// Nothing now.

View File

@ -0,0 +1,213 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2020 Jeff Epler for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "shared-bindings/_canio/Message.h"
#include "shared-module/_canio/Message.h"
#include "py/obj.h"
#include "py/objproperty.h"
#include "py/runtime.h"
//| class Message:
//| def __init__(self, id: int=0, data: Optional[bytes] = None, *, size: Optional[int] = None, rtr: bool = False):
//| """Construct a Message to send on a CAN bus
//|
//| :param int id: The numeric ID of the message
//| :param bytes data: The content of the message
//| :param int size: The amount of data requested, for an rtr
//| :param bool rtr: True if the message represents an rtr (Remote Transmission Request)
//|
//| In CAN, messages can have a size from 0 to 8 bytes.
//|
//| For a non-rtr message, specify `data`. For an rtr-message, specify either `data` (a dummy buffer of the requested size) or `size`.
//| """
//| ...
//|
STATIC mp_obj_t canio_message_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_id, ARG_data, ARG_size, ARG_rtr, NUM_ARGS };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_id, MP_ARG_INT, {.u_obj = 0} },
{ MP_QSTR_data, MP_ARG_OBJ, {.u_obj = 0} },
{ MP_QSTR_size, MP_ARG_INT, {.u_int = -1} },
{ MP_QSTR_rtr, MP_ARG_BOOL, {.u_bool = false} },
};
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
MP_STATIC_ASSERT( MP_ARRAY_SIZE(allowed_args) == NUM_ARGS );
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
bool rtr = args[ARG_rtr].u_bool;
size_t size = (size_t)args[ARG_size].u_int;
bool specified_size = (size != (size_t)-1);
bool specified_data = (args[ARG_data].u_obj != NULL);
if(specified_size && specified_data) {
mp_raise_TypeError(translate("specify size or data, but not both"));
}
mp_buffer_info_t data;
if (specified_data) {
mp_get_buffer_raise(args[ARG_data].u_obj, &data, MP_BUFFER_READ);
} else if (specified_size) {
data.buf = 0;
data.len = size;
} else {
data.buf = 0;
data.len = 0;
}
if(data.len > 8) {
mp_raise_ValueError(translate("Messages limited to 8 bytes"));
}
canio_message_obj_t *self = m_new_obj(canio_message_obj_t);
self->base.type = &canio_message_type;
common_hal_canio_message_construct(self, args[ARG_id].u_int, data.buf, data.len, rtr);
return self;
}
//| id: int
//| """The numeric ID of the message"""
//|
STATIC mp_obj_t canio_message_id_get(const mp_obj_t self_in) {
canio_message_obj_t *self = self_in;
return MP_OBJ_NEW_SMALL_INT(common_hal_canio_message_id_get(self));
}
MP_DEFINE_CONST_FUN_OBJ_1(canio_message_id_get_obj, canio_message_id_get);
STATIC mp_obj_t canio_message_id_set(const mp_obj_t self_in, const mp_obj_t id) {
canio_message_obj_t *self = self_in;
common_hal_canio_message_id_set(self, mp_obj_get_int(id));
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_2(canio_message_id_set_obj, canio_message_id_set);
STATIC const mp_obj_property_t canio_message_id_obj = {
.base.type = &mp_type_property,
.proxy = {(mp_obj_t)&canio_message_id_get_obj,
(mp_obj_t)&canio_message_id_set_obj,
(mp_obj_t)&mp_const_none_obj},
};
//| data: bytes
//| """The content of the message, or dummy content in the case of an rtr.
//|
//| Assigning to data sets the bytes to zero"""
//|
STATIC mp_obj_t canio_message_data_get(const mp_obj_t self_in) {
canio_message_obj_t *self = self_in;
return mp_obj_new_bytes((const byte*)common_hal_canio_message_data_get(self), common_hal_canio_message_size_get(self));
}
MP_DEFINE_CONST_FUN_OBJ_1(canio_message_data_get_obj, canio_message_data_get);
STATIC mp_obj_t canio_message_data_set(const mp_obj_t self_in, const mp_obj_t data_in) {
canio_message_obj_t *self = self_in;
mp_buffer_info_t data;
mp_get_buffer_raise(data_in, &data, MP_BUFFER_READ);
if(data.len > 8) {
mp_raise_ValueError(translate("Messages limited to 8 bytes"));
}
common_hal_canio_message_data_set(self, data.buf, data.len);
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_2(canio_message_data_set_obj, canio_message_data_set);
STATIC const mp_obj_property_t canio_message_data_obj = {
.base.type = &mp_type_property,
.proxy = {(mp_obj_t)&canio_message_data_get_obj,
(mp_obj_t)&canio_message_data_set_obj,
(mp_obj_t)&mp_const_none_obj},
};
//| size: int
//| """The length of the message, or the length of the requested data in the case of an rtr"""
//|
STATIC mp_obj_t canio_message_size_get(const mp_obj_t self_in) {
canio_message_obj_t *self = self_in;
return MP_OBJ_NEW_SMALL_INT(common_hal_canio_message_size_get(self));
}
MP_DEFINE_CONST_FUN_OBJ_1(canio_message_size_get_obj, canio_message_size_get);
STATIC mp_obj_t canio_message_size_set(const mp_obj_t self_in, const mp_obj_t size_in) {
canio_message_obj_t *self = self_in;
int size = mp_obj_get_int(size_in);
if(size > 8) {
mp_raise_ValueError(translate("Messages limited to 8 bytes"));
}
common_hal_canio_message_size_set(self, size);
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_2(canio_message_size_set_obj, canio_message_size_set);
STATIC const mp_obj_property_t canio_message_size_obj = {
.base.type = &mp_type_property,
.proxy = {(mp_obj_t)&canio_message_size_get_obj,
(mp_obj_t)&canio_message_size_set_obj,
(mp_obj_t)&mp_const_none_obj},
};
//| rtr: bool
//| """True if the message represents a remote transmission request (RTR)"""
//|
STATIC mp_obj_t canio_message_rtr_get(const mp_obj_t self_in) {
canio_message_obj_t *self = self_in;
return mp_obj_new_bool(common_hal_canio_message_rtr_get(self));
}
MP_DEFINE_CONST_FUN_OBJ_1(canio_message_rtr_get_obj, canio_message_rtr_get);
STATIC mp_obj_t canio_message_rtr_set(const mp_obj_t self_in, const mp_obj_t rtr) {
canio_message_obj_t *self = self_in;
common_hal_canio_message_size_set(self, mp_obj_is_true(rtr));
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_2(canio_message_rtr_set_obj, canio_message_rtr_set);
STATIC const mp_obj_property_t canio_message_rtr_obj = {
.base.type = &mp_type_property,
.proxy = {(mp_obj_t)&canio_message_rtr_get_obj,
(mp_obj_t)&canio_message_rtr_set_obj,
(mp_obj_t)&mp_const_none_obj},
};
STATIC const mp_rom_map_elem_t canio_message_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_id), MP_ROM_PTR(&canio_message_id_obj) },
{ MP_ROM_QSTR(MP_QSTR_data), MP_ROM_PTR(&canio_message_data_obj) },
{ MP_ROM_QSTR(MP_QSTR_size), MP_ROM_PTR(&canio_message_size_obj) },
{ MP_ROM_QSTR(MP_QSTR_rtr), MP_ROM_PTR(&canio_message_rtr_obj) },
};
STATIC MP_DEFINE_CONST_DICT(canio_message_locals_dict, canio_message_locals_dict_table);
const mp_obj_type_t canio_message_type = {
{ &mp_type_type },
.name = MP_QSTR_Message,
.make_new = canio_message_make_new,
.locals_dict = (mp_obj_t)&canio_message_locals_dict,
};

View File

@ -0,0 +1,31 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2020 Jeff Epler for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#pragma once
#include "py/obj.h"
extern const mp_obj_type_t canio_message_type;

View File

@ -0,0 +1,73 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2020 Jeff Epler for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
//| """CAN bus access
//|
//| The `_canio` module contains low level classes to support the CAN bus
//| protocol.
//|
//| All classes change hardware state and should be deinitialized when they
//| are no longer needed if the program continues after use. To do so, either
//| call :py:meth:`!deinit` or use a context manager. See
//| :ref:`lifetime-and-contextmanagers` for more info.
//|
//| For example::
//|
//| import _canio
//| from board import *
//|
//| can = _canio.BUS(board.CANRX, board.CANTX)
//| can.write(408, b"adafruit")
//| can.deinit()
//|
//| This example will write the data 'adafruit' onto the CAN bus to any
//| device listening for message id 408."""
//|
#include "py/obj.h"
#include "shared-bindings/_canio/__init__.h"
#include "shared-bindings/_canio/CAN.h"
#include "shared-bindings/_canio/Match.h"
#include "shared-bindings/_canio/Message.h"
STATIC const mp_rom_map_elem_t canio_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR__canio) },
{ MP_ROM_QSTR(MP_QSTR_CAN), MP_ROM_PTR(&canio_can_type) },
{ MP_ROM_QSTR(MP_QSTR_Match), MP_ROM_PTR(&canio_match_type) },
{ MP_ROM_QSTR(MP_QSTR_Message), MP_ROM_PTR(&canio_message_type) },
#if 0
{ MP_ROM_QSTR(MP_QSTR_Listener), MP_ROM_PTR(&canio_listener_type) },
#endif
};
STATIC MP_DEFINE_CONST_DICT(canio_module_globals, canio_module_globals_table);
const mp_obj_module_t canio_module = {
.base = { &mp_type_module },
.globals = (mp_obj_dict_t*)&canio_module_globals,
};

View File

@ -0,0 +1,29 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2020 Jeff Epler for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#pragma once
// Nothing now.

View File

@ -0,0 +1,43 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2020 Jeff Epler for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "shared-module/_canio/Match.h"
void common_hal_canio_match_construct(canio_match_obj_t *self, int address, int mask, bool extended) {
self->address = address;
self->mask = mask;
self->extended = extended;
}
int common_hal_canio_match_address_get(const canio_match_obj_t *self) {
return self->address;
}
int common_hal_canio_match_mask_get(const canio_match_obj_t *self) {
return self->mask;
}
bool common_hal_canio_match_extended_get(const canio_match_obj_t *self) {
return self->extended;
}

View File

@ -0,0 +1,41 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2020 Jeff Epler for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#pragma once
#include "py/obj.h"
typedef struct {
mp_obj_base_t base;
int address;
int mask;
bool extended;
} canio_match_obj_t;
void common_hal_canio_match_construct(canio_match_obj_t *self, int address, int mask, bool extended);
int common_hal_canio_match_address_get(const canio_match_obj_t *self);
int common_hal_canio_match_mask_get(const canio_match_obj_t *self);
bool common_hal_canio_match_extended_get(const canio_match_obj_t *self);

View File

@ -0,0 +1,85 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2020 Jeff Epler for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "shared-module/_canio/Message.h"
#include <string.h>
void common_hal_canio_message_construct(canio_message_obj_t *self, int id, void *data, size_t size, bool rtr)
{
self->id = id;
self->size = size;
self->rtr = rtr;
if (data) {
memcpy(self->data, data, size);
} else {
memset(self->data, 0, size);
}
}
int common_hal_canio_message_id_get(const canio_message_obj_t *self)
{
return self->id;
}
void common_hal_canio_message_id_set(canio_message_obj_t *self, int id)
{
self->id = id;
}
const void *common_hal_canio_message_data_get(const canio_message_obj_t *self)
{
return self->data;
}
const void common_hal_canio_message_data_set(canio_message_obj_t *self, const void *data, size_t size)
{
memcpy(self->data, data, size);
}
size_t common_hal_canio_message_size_get(const canio_message_obj_t *self)
{
return self->size;
}
void common_hal_canio_message_size_set(canio_message_obj_t *self, size_t size)
{
memset(self->data, 0, size);
self->size = size;
}
bool common_hal_canio_message_rtr_get(const canio_message_obj_t *self)
{
return self->rtr;
}
void common_hal_canio_message_rtr_set(canio_message_obj_t *self, bool rtr)
{
self->rtr = rtr;
}

View File

@ -0,0 +1,47 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2020 Jeff Epler for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#pragma once
#include "py/obj.h"
typedef struct {
mp_obj_base_t base;
int id;
size_t size;
uint8_t data[8];
bool rtr;
} canio_message_obj_t;
void common_hal_canio_message_construct(canio_message_obj_t *self, int id, void *data, size_t size, bool rtr);
bool common_hal_canio_message_rtr_get(const canio_message_obj_t *self);
int common_hal_canio_message_id_get(const canio_message_obj_t *self);
const void *common_hal_canio_message_data_get(const canio_message_obj_t *self);
size_t common_hal_canio_message_size_get(const canio_message_obj_t *self);
void common_hal_canio_message_rtr_set(canio_message_obj_t *self, bool rtr);
void common_hal_canio_message_id_set(canio_message_obj_t *self, int id);
void common_hal_canio_message_data_set(canio_message_obj_t *self, const void *data, size_t size);
void common_hal_canio_message_size_set(canio_message_obj_t *self, size_t size);