| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531 |
- /*
- * This file is part of the MicroPython project, http://micropython.org/
- *
- * The MIT License (MIT)
- *
- * Copyright (c) 2013, 2014 Damien P. George
- * Copyright (c) 2015 Daniel Campora
- *
- * 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 <stdio.h>
- #include <string.h>
- #include "py/runtime.h"
- #include "py/mperrno.h"
- #include "py/mphal.h"
- #include "bufhelper.h"
- #include "inc/hw_types.h"
- #include "inc/hw_i2c.h"
- #include "inc/hw_ints.h"
- #include "inc/hw_memmap.h"
- #include "rom_map.h"
- #include "pin.h"
- #include "prcm.h"
- #include "i2c.h"
- #include "pybi2c.h"
- #include "mpexception.h"
- #include "pybsleep.h"
- #include "utils.h"
- #include "pybpin.h"
- #include "pins.h"
- /// \moduleref pyb
- /// \class I2C - a two-wire serial protocol
- typedef struct _pyb_i2c_obj_t {
- mp_obj_base_t base;
- uint baudrate;
- } pyb_i2c_obj_t;
- /******************************************************************************
- DEFINE CONSTANTS
- ******************************************************************************/
- #define PYBI2C_MIN_BAUD_RATE_HZ (50000)
- #define PYBI2C_MAX_BAUD_RATE_HZ (400000)
- #define PYBI2C_TRANSC_TIMEOUT_MS (20)
- #define PYBI2C_TRANSAC_WAIT_DELAY_US (10)
- #define PYBI2C_TIMEOUT_TO_COUNT(to_us, baud) (((baud) * to_us) / 16000000)
- #define RET_IF_ERR(Func) { \
- if (!Func) { \
- return false; \
- } \
- }
- /******************************************************************************
- DECLARE PRIVATE DATA
- ******************************************************************************/
- STATIC pyb_i2c_obj_t pyb_i2c_obj = {.baudrate = 0};
- /******************************************************************************
- DECLARE PRIVATE FUNCTIONS
- ******************************************************************************/
- STATIC bool pyb_i2c_write(byte addr, byte *data, uint len, bool stop);
- /******************************************************************************
- DEFINE PRIVATE FUNCTIONS
- ******************************************************************************/
- // only master mode is available for the moment
- STATIC void i2c_init (pyb_i2c_obj_t *self) {
- // Enable the I2C Peripheral
- MAP_PRCMPeripheralClkEnable(PRCM_I2CA0, PRCM_RUN_MODE_CLK | PRCM_SLP_MODE_CLK);
- MAP_PRCMPeripheralReset(PRCM_I2CA0);
- // Configure I2C module with the specified baudrate
- MAP_I2CMasterInitExpClk(I2CA0_BASE, self->baudrate);
- }
- STATIC bool pyb_i2c_transaction(uint cmd) {
- // Convert the timeout to microseconds
- int32_t timeout = PYBI2C_TRANSC_TIMEOUT_MS * 1000;
- // Sanity check, t_timeout must be between 1 and 255
- uint t_timeout = MIN(PYBI2C_TIMEOUT_TO_COUNT(timeout, pyb_i2c_obj.baudrate), 255);
- // Clear all interrupts
- MAP_I2CMasterIntClearEx(I2CA0_BASE, MAP_I2CMasterIntStatusEx(I2CA0_BASE, false));
- // Set the time-out in terms of clock cycles. Not to be used with breakpoints.
- MAP_I2CMasterTimeoutSet(I2CA0_BASE, t_timeout);
- // Initiate the transfer.
- MAP_I2CMasterControl(I2CA0_BASE, cmd);
- // Wait until the current byte has been transferred.
- // Poll on the raw interrupt status.
- while ((MAP_I2CMasterIntStatusEx(I2CA0_BASE, false) & (I2C_MASTER_INT_DATA | I2C_MASTER_INT_TIMEOUT)) == 0) {
- if (timeout < 0) {
- // the peripheral is not responding, so stop
- return false;
- }
- // wait for a few microseconds
- UtilsDelay(UTILS_DELAY_US_TO_COUNT(PYBI2C_TRANSAC_WAIT_DELAY_US));
- timeout -= PYBI2C_TRANSAC_WAIT_DELAY_US;
- }
- // Check for any errors in the transfer
- if (MAP_I2CMasterErr(I2CA0_BASE) != I2C_MASTER_ERR_NONE) {
- switch(cmd) {
- case I2C_MASTER_CMD_BURST_SEND_START:
- case I2C_MASTER_CMD_BURST_SEND_CONT:
- case I2C_MASTER_CMD_BURST_SEND_STOP:
- MAP_I2CMasterControl(I2CA0_BASE, I2C_MASTER_CMD_BURST_SEND_ERROR_STOP);
- break;
- case I2C_MASTER_CMD_BURST_RECEIVE_START:
- case I2C_MASTER_CMD_BURST_RECEIVE_CONT:
- case I2C_MASTER_CMD_BURST_RECEIVE_FINISH:
- MAP_I2CMasterControl(I2CA0_BASE, I2C_MASTER_CMD_BURST_RECEIVE_ERROR_STOP);
- break;
- default:
- break;
- }
- return false;
- }
- return true;
- }
- STATIC void pyb_i2c_check_init(pyb_i2c_obj_t *self) {
- // not initialized
- if (!self->baudrate) {
- mp_raise_OSError(MP_EPERM);
- }
- }
- STATIC bool pyb_i2c_scan_device(byte devAddr) {
- bool ret = false;
- // Set the I2C slave address
- MAP_I2CMasterSlaveAddrSet(I2CA0_BASE, devAddr, true);
- // Initiate the transfer.
- if (pyb_i2c_transaction(I2C_MASTER_CMD_SINGLE_RECEIVE)) {
- ret = true;
- }
- // Send the stop bit to cancel the read transaction
- MAP_I2CMasterControl(I2CA0_BASE, I2C_MASTER_CMD_BURST_SEND_ERROR_STOP);
- if (!ret) {
- uint8_t data = 0;
- if (pyb_i2c_write(devAddr, &data, sizeof(data), true)) {
- ret = true;
- }
- }
- return ret;
- }
- STATIC bool pyb_i2c_mem_addr_write (byte addr, byte *mem_addr, uint mem_addr_len) {
- // Set I2C codec slave address
- MAP_I2CMasterSlaveAddrSet(I2CA0_BASE, addr, false);
- // Write the first byte to the controller.
- MAP_I2CMasterDataPut(I2CA0_BASE, *mem_addr++);
- // Initiate the transfer.
- RET_IF_ERR(pyb_i2c_transaction(I2C_MASTER_CMD_BURST_SEND_START));
- // Loop until the completion of transfer or error
- while (--mem_addr_len) {
- // Write the next byte of data
- MAP_I2CMasterDataPut(I2CA0_BASE, *mem_addr++);
- // Transact over I2C to send the next byte
- RET_IF_ERR(pyb_i2c_transaction(I2C_MASTER_CMD_BURST_SEND_CONT));
- }
- return true;
- }
- STATIC bool pyb_i2c_mem_write (byte addr, byte *mem_addr, uint mem_addr_len, byte *data, uint data_len) {
- if (pyb_i2c_mem_addr_write (addr, mem_addr, mem_addr_len)) {
- // Loop until the completion of transfer or error
- while (data_len--) {
- // Write the next byte of data
- MAP_I2CMasterDataPut(I2CA0_BASE, *data++);
- // Transact over I2C to send the byte
- RET_IF_ERR(pyb_i2c_transaction(I2C_MASTER_CMD_BURST_SEND_CONT));
- }
- // send the stop bit
- RET_IF_ERR(pyb_i2c_transaction(I2C_MASTER_CMD_BURST_SEND_STOP));
- return true;
- }
- return false;
- }
- STATIC bool pyb_i2c_write(byte addr, byte *data, uint len, bool stop) {
- // Set I2C codec slave address
- MAP_I2CMasterSlaveAddrSet(I2CA0_BASE, addr, false);
- // Write the first byte to the controller.
- MAP_I2CMasterDataPut(I2CA0_BASE, *data++);
- // Initiate the transfer.
- RET_IF_ERR(pyb_i2c_transaction(I2C_MASTER_CMD_BURST_SEND_START));
- // Loop until the completion of transfer or error
- while (--len) {
- // Write the next byte of data
- MAP_I2CMasterDataPut(I2CA0_BASE, *data++);
- // Transact over I2C to send the byte
- RET_IF_ERR(pyb_i2c_transaction(I2C_MASTER_CMD_BURST_SEND_CONT));
- }
- // If a stop bit is to be sent, do it.
- if (stop) {
- RET_IF_ERR(pyb_i2c_transaction(I2C_MASTER_CMD_BURST_SEND_STOP));
- }
- return true;
- }
- STATIC bool pyb_i2c_read(byte addr, byte *data, uint len) {
- // Initiate a burst or single receive sequence
- uint cmd = --len > 0 ? I2C_MASTER_CMD_BURST_RECEIVE_START : I2C_MASTER_CMD_SINGLE_RECEIVE;
- // Set I2C codec slave address
- MAP_I2CMasterSlaveAddrSet(I2CA0_BASE, addr, true);
- // Initiate the transfer.
- RET_IF_ERR(pyb_i2c_transaction(cmd));
- // Loop until the completion of reception or error
- while (len) {
- // Receive the byte over I2C
- *data++ = MAP_I2CMasterDataGet(I2CA0_BASE);
- if (--len) {
- // Continue with reception
- RET_IF_ERR(pyb_i2c_transaction(I2C_MASTER_CMD_BURST_RECEIVE_CONT));
- } else {
- // Complete the last reception
- RET_IF_ERR(pyb_i2c_transaction(I2C_MASTER_CMD_BURST_RECEIVE_FINISH));
- }
- }
- // Receive the last byte over I2C
- *data = MAP_I2CMasterDataGet(I2CA0_BASE);
- return true;
- }
- STATIC void pyb_i2c_read_into (mp_arg_val_t *args, vstr_t *vstr) {
- pyb_i2c_check_init(&pyb_i2c_obj);
- // get the buffer to receive into
- pyb_buf_get_for_recv(args[1].u_obj, vstr);
- // receive the data
- if (!pyb_i2c_read(args[0].u_int, (byte *)vstr->buf, vstr->len)) {
- mp_raise_OSError(MP_EIO);
- }
- }
- STATIC void pyb_i2c_readmem_into (mp_arg_val_t *args, vstr_t *vstr) {
- pyb_i2c_check_init(&pyb_i2c_obj);
- // get the buffer to receive into
- pyb_buf_get_for_recv(args[2].u_obj, vstr);
- // get the addresses
- mp_uint_t i2c_addr = args[0].u_int;
- mp_uint_t mem_addr = args[1].u_int;
- // determine the width of mem_addr (1 or 2 bytes)
- mp_uint_t mem_addr_size = args[3].u_int >> 3;
- // write the register address to be read from
- if (pyb_i2c_mem_addr_write (i2c_addr, (byte *)&mem_addr, mem_addr_size)) {
- // Read the specified length of data
- if (!pyb_i2c_read (i2c_addr, (byte *)vstr->buf, vstr->len)) {
- mp_raise_OSError(MP_EIO);
- }
- } else {
- mp_raise_OSError(MP_EIO);
- }
- }
- /******************************************************************************/
- /* MicroPython bindings */
- /******************************************************************************/
- STATIC void pyb_i2c_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
- pyb_i2c_obj_t *self = self_in;
- if (self->baudrate > 0) {
- mp_printf(print, "I2C(0, baudrate=%u)", self->baudrate);
- } else {
- mp_print_str(print, "I2C(0)");
- }
- }
- STATIC mp_obj_t pyb_i2c_init_helper(pyb_i2c_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
- enum { ARG_scl, ARG_sda, ARG_freq };
- static const mp_arg_t allowed_args[] = {
- { MP_QSTR_scl, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
- { MP_QSTR_sda, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
- { MP_QSTR_freq, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 100000} },
- };
- mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
- mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
- // make sure the baudrate is between the valid range
- self->baudrate = MIN(MAX(args[ARG_freq].u_int, PYBI2C_MIN_BAUD_RATE_HZ), PYBI2C_MAX_BAUD_RATE_HZ);
- // assign the pins
- mp_obj_t pins[2] = {&pin_GP13, &pin_GP23}; // default (SDA, SCL) pins
- if (args[ARG_scl].u_obj != MP_OBJ_NULL) {
- pins[1] = args[ARG_scl].u_obj;
- }
- if (args[ARG_sda].u_obj != MP_OBJ_NULL) {
- pins[0] = args[ARG_sda].u_obj;
- }
- pin_assign_pins_af(pins, 2, PIN_TYPE_STD_PU, PIN_FN_I2C, 0);
- // init the I2C bus
- i2c_init(self);
- // register it with the sleep module
- pyb_sleep_add ((const mp_obj_t)self, (WakeUpCB_t)i2c_init);
- return mp_const_none;
- }
- STATIC mp_obj_t pyb_i2c_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
- // check the id argument, if given
- if (n_args > 0) {
- if (all_args[0] != MP_OBJ_NEW_SMALL_INT(0)) {
- mp_raise_OSError(MP_ENODEV);
- }
- --n_args;
- ++all_args;
- }
- // parse args
- mp_map_t kw_args;
- mp_map_init_fixed_table(&kw_args, n_kw, all_args + n_args);
- // setup the object
- pyb_i2c_obj_t *self = &pyb_i2c_obj;
- self->base.type = &pyb_i2c_type;
- // start the peripheral
- pyb_i2c_init_helper(self, n_args, all_args, &kw_args);
- return (mp_obj_t)self;
- }
- STATIC mp_obj_t pyb_i2c_init(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
- return pyb_i2c_init_helper(pos_args[0], n_args - 1, pos_args + 1, kw_args);
- }
- STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_i2c_init_obj, 1, pyb_i2c_init);
- STATIC mp_obj_t pyb_i2c_deinit(mp_obj_t self_in) {
- // disable the peripheral
- MAP_I2CMasterDisable(I2CA0_BASE);
- MAP_PRCMPeripheralClkDisable(PRCM_I2CA0, PRCM_RUN_MODE_CLK | PRCM_SLP_MODE_CLK);
- // invalidate the baudrate
- pyb_i2c_obj.baudrate = 0;
- // unregister it with the sleep module
- pyb_sleep_remove ((const mp_obj_t)self_in);
- return mp_const_none;
- }
- STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_i2c_deinit_obj, pyb_i2c_deinit);
- STATIC mp_obj_t pyb_i2c_scan(mp_obj_t self_in) {
- pyb_i2c_check_init(&pyb_i2c_obj);
- mp_obj_t list = mp_obj_new_list(0, NULL);
- for (uint addr = 0x08; addr <= 0x77; addr++) {
- for (int i = 0; i < 3; i++) {
- if (pyb_i2c_scan_device(addr)) {
- mp_obj_list_append(list, mp_obj_new_int(addr));
- break;
- }
- }
- }
- return list;
- }
- STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_i2c_scan_obj, pyb_i2c_scan);
- STATIC mp_obj_t pyb_i2c_readfrom(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
- STATIC const mp_arg_t pyb_i2c_readfrom_args[] = {
- { MP_QSTR_addr, MP_ARG_REQUIRED | MP_ARG_INT, },
- { MP_QSTR_nbytes, MP_ARG_REQUIRED | MP_ARG_OBJ, },
- };
- // parse args
- mp_arg_val_t args[MP_ARRAY_SIZE(pyb_i2c_readfrom_args)];
- mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(args), pyb_i2c_readfrom_args, args);
- vstr_t vstr;
- pyb_i2c_read_into(args, &vstr);
- // return the received data
- return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
- }
- STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_i2c_readfrom_obj, 3, pyb_i2c_readfrom);
- STATIC mp_obj_t pyb_i2c_readfrom_into(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
- STATIC const mp_arg_t pyb_i2c_readfrom_into_args[] = {
- { MP_QSTR_addr, MP_ARG_REQUIRED | MP_ARG_INT, },
- { MP_QSTR_buf, MP_ARG_REQUIRED | MP_ARG_OBJ, },
- };
- // parse args
- mp_arg_val_t args[MP_ARRAY_SIZE(pyb_i2c_readfrom_into_args)];
- mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(args), pyb_i2c_readfrom_into_args, args);
- vstr_t vstr;
- pyb_i2c_read_into(args, &vstr);
- // return the number of bytes received
- return mp_obj_new_int(vstr.len);
- }
- STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_i2c_readfrom_into_obj, 1, pyb_i2c_readfrom_into);
- STATIC mp_obj_t pyb_i2c_writeto(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
- STATIC const mp_arg_t pyb_i2c_writeto_args[] = {
- { MP_QSTR_addr, MP_ARG_REQUIRED | MP_ARG_INT, },
- { MP_QSTR_buf, MP_ARG_REQUIRED | MP_ARG_OBJ, },
- { MP_QSTR_stop, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = true} },
- };
- // parse args
- mp_arg_val_t args[MP_ARRAY_SIZE(pyb_i2c_writeto_args)];
- mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(args), pyb_i2c_writeto_args, args);
- pyb_i2c_check_init(&pyb_i2c_obj);
- // get the buffer to send from
- mp_buffer_info_t bufinfo;
- uint8_t data[1];
- pyb_buf_get_for_send(args[1].u_obj, &bufinfo, data);
- // send the data
- if (!pyb_i2c_write(args[0].u_int, bufinfo.buf, bufinfo.len, args[2].u_bool)) {
- mp_raise_OSError(MP_EIO);
- }
- // return the number of bytes written
- return mp_obj_new_int(bufinfo.len);
- }
- STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_i2c_writeto_obj, 1, pyb_i2c_writeto);
- STATIC mp_obj_t pyb_i2c_readfrom_mem(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
- STATIC const mp_arg_t pyb_i2c_readfrom_mem_args[] = {
- { MP_QSTR_addr, MP_ARG_REQUIRED | MP_ARG_INT, },
- { MP_QSTR_memaddr, MP_ARG_REQUIRED | MP_ARG_INT, },
- { MP_QSTR_nbytes, MP_ARG_REQUIRED | MP_ARG_OBJ, },
- { MP_QSTR_addrsize, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 8} },
- };
- // parse args
- mp_arg_val_t args[MP_ARRAY_SIZE(pyb_i2c_readfrom_mem_args)];
- mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(args), pyb_i2c_readfrom_mem_args, args);
- vstr_t vstr;
- pyb_i2c_readmem_into (args, &vstr);
- return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
- }
- STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_i2c_readfrom_mem_obj, 1, pyb_i2c_readfrom_mem);
- STATIC const mp_arg_t pyb_i2c_readfrom_mem_into_args[] = {
- { MP_QSTR_addr, MP_ARG_REQUIRED | MP_ARG_INT, },
- { MP_QSTR_memaddr, MP_ARG_REQUIRED | MP_ARG_INT, },
- { MP_QSTR_buf, MP_ARG_REQUIRED | MP_ARG_OBJ, },
- { MP_QSTR_addrsize, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 8} },
- };
- STATIC mp_obj_t pyb_i2c_readfrom_mem_into(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
- // parse args
- mp_arg_val_t args[MP_ARRAY_SIZE(pyb_i2c_readfrom_mem_into_args)];
- mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(args), pyb_i2c_readfrom_mem_into_args, args);
- // get the buffer to read into
- vstr_t vstr;
- pyb_i2c_readmem_into (args, &vstr);
- return mp_const_none;
- }
- STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_i2c_readfrom_mem_into_obj, 1, pyb_i2c_readfrom_mem_into);
- STATIC mp_obj_t pyb_i2c_writeto_mem(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
- // parse args
- mp_arg_val_t args[MP_ARRAY_SIZE(pyb_i2c_readfrom_mem_into_args)];
- mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(pyb_i2c_readfrom_mem_into_args), pyb_i2c_readfrom_mem_into_args, args);
- pyb_i2c_check_init(&pyb_i2c_obj);
- // get the buffer to write from
- mp_buffer_info_t bufinfo;
- uint8_t data[1];
- pyb_buf_get_for_send(args[2].u_obj, &bufinfo, data);
- // get the addresses
- mp_uint_t i2c_addr = args[0].u_int;
- mp_uint_t mem_addr = args[1].u_int;
- // determine the width of mem_addr (1 or 2 bytes)
- mp_uint_t mem_addr_size = args[3].u_int >> 3;
- // write the register address to write to.
- if (pyb_i2c_mem_write (i2c_addr, (byte *)&mem_addr, mem_addr_size, bufinfo.buf, bufinfo.len)) {
- return mp_const_none;
- }
- mp_raise_OSError(MP_EIO);
- }
- STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_i2c_writeto_mem_obj, 1, pyb_i2c_writeto_mem);
- STATIC const mp_rom_map_elem_t pyb_i2c_locals_dict_table[] = {
- // instance methods
- { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&pyb_i2c_init_obj) },
- { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&pyb_i2c_deinit_obj) },
- { MP_ROM_QSTR(MP_QSTR_scan), MP_ROM_PTR(&pyb_i2c_scan_obj) },
- { MP_ROM_QSTR(MP_QSTR_readfrom), MP_ROM_PTR(&pyb_i2c_readfrom_obj) },
- { MP_ROM_QSTR(MP_QSTR_readfrom_into), MP_ROM_PTR(&pyb_i2c_readfrom_into_obj) },
- { MP_ROM_QSTR(MP_QSTR_writeto), MP_ROM_PTR(&pyb_i2c_writeto_obj) },
- { MP_ROM_QSTR(MP_QSTR_readfrom_mem), MP_ROM_PTR(&pyb_i2c_readfrom_mem_obj) },
- { MP_ROM_QSTR(MP_QSTR_readfrom_mem_into), MP_ROM_PTR(&pyb_i2c_readfrom_mem_into_obj) },
- { MP_ROM_QSTR(MP_QSTR_writeto_mem), MP_ROM_PTR(&pyb_i2c_writeto_mem_obj) },
- };
- STATIC MP_DEFINE_CONST_DICT(pyb_i2c_locals_dict, pyb_i2c_locals_dict_table);
- const mp_obj_type_t pyb_i2c_type = {
- { &mp_type_type },
- .name = MP_QSTR_I2C,
- .print = pyb_i2c_print,
- .make_new = pyb_i2c_make_new,
- .locals_dict = (mp_obj_t)&pyb_i2c_locals_dict,
- };
|