pybi2c.c 20 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
/*
 * This file is part of the Micro Python 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/mpstate.h"
#include MICROPY_HAL_H
33
#include "py/runtime.h"
34
35
36
37
38
39
40
41
42
43
44
#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"
45
#include "pybsleep.h"
46
#include "utils.h"
47
48
49
50
51
52
53
54
55
56
57
58
59

/// \moduleref pyb
/// \class I2C - a two-wire serial protocol
///
/// I2C is a two-wire protocol for communicating between devices.  At the physical
/// level it consists of 2 wires: SCL and SDA, the clock and data lines respectively.
///
/// I2C objects are created attached to a specific bus.  They can be initialised
/// when created, or initialised later on:
///
///     from pyb import I2C
///
///     i2c = I2C()                          # create
60
61
///     i2c = I2C(50000)                     # create and init with a 50KHz baudrate
///     i2c.init(100000)                     # init with a 100KHz baudrate
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
///     i2c.deinit()                         # turn off the peripheral
///
/// Printing the i2c object gives you information about its configuration.
///
/// Basic methods for slave are send and recv:
///
///     i2c.send('abc')      # send 3 bytes
///     i2c.send(0x42)       # send a single byte, given by the number
///     data = i2c.recv(3)   # receive 3 bytes
///
/// To receive inplace, first create a bytearray:
///
///     data = bytearray(3)  # create a buffer
///     i2c.recv(data)       # receive 3 bytes, writing them into data
///
/// A master must specify the recipient's address:
///
79
///     i2c.init(100000)
80
81
82
83
84
///     i2c.send('123', 0x42)        # send 3 bytes to slave with address 0x42
///     i2c.send(b'456', addr=0x42)  # keyword for address
///
/// Master also has other methods:
///
85
86
87
88
89
90
91
///     i2c.is_ready(0x42)              # check if slave 0x42 is ready
///     i2c.scan()                      # scan for slaves on the bus, returning
///                                     #   a list of valid addresses
///     i2c.mem_read(3, 0x42, 2)        # read 3 bytes from memory of slave 0x42,
///                                     #   starting at address 2 in the slave
///     i2c.mem_write('abc', 0x42, 2)   # write 3 bytes to memory of slave 0x42,
///                                     #   starting at address 2 in the slave
92

93
94
typedef struct _pyb_i2c_obj_t {
    mp_obj_base_t base;
95
    uint baudrate;
96
97
} pyb_i2c_obj_t;

98
99
100
/******************************************************************************
 DEFINE CONSTANTS
 ******************************************************************************/
danicampora's avatar
danicampora committed
101
#define PYBI2C_MIN_BAUD_RATE_HZ                (50000)
102
103
#define PYBI2C_MAX_BAUD_RATE_HZ                (400000)

104
#define PYBI2C_TRANSC_TIMEOUT_MS               (10)
105
#define PYBI2C_TRANSAC_WAIT_DELAY_US           (10)
106

107
#define PYBI2C_TIMEOUT_TO_COUNT(to_us, baud)   (((baud) * to_us) / 16000000)
108
109
110
111
112
113
114

#define RET_IF_ERR(Func)                        {                           \
                                                    if (!Func) {            \
                                                        return  false;      \
                                                    }                       \
                                                }

115
116
117
/******************************************************************************
 DECLARE PRIVATE DATA
 ******************************************************************************/
danicampora's avatar
danicampora committed
118
STATIC pyb_i2c_obj_t pyb_i2c_obj = {.baudrate = 0};
119

120
/******************************************************************************
121
 DEFINE PRIVATE FUNCTIONS
122
123
 ******************************************************************************/
// only master mode is available for the moment
124
STATIC void i2c_init (pyb_i2c_obj_t *self) {
125
126
127
128
    // 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
129
    MAP_I2CMasterInitExpClk(I2CA0_BASE, self->baudrate);
130
131
}

132
133
134
STATIC bool pyb_i2c_transaction(uint cmd) {
    // Convert the timeout to microseconds
    int32_t timeout = PYBI2C_TRANSC_TIMEOUT_MS * 1000;
135
136
    // Sanity check, t_timeout must be between 1 and 255
    uint t_timeout = MIN(PYBI2C_TIMEOUT_TO_COUNT(timeout, pyb_i2c_obj.baudrate), 255);
137
138
    // Clear all interrupts
    MAP_I2CMasterIntClearEx(I2CA0_BASE, MAP_I2CMasterIntStatusEx(I2CA0_BASE, false));
139
140
    // Set the time-out in terms of clock cycles. Not to be used with breakpoints.
    MAP_I2CMasterTimeoutSet(I2CA0_BASE, t_timeout);
141
142
143
144
    // Initiate the transfer.
    MAP_I2CMasterControl(I2CA0_BASE, cmd);
    // Wait until the current byte has been transferred.
    // Poll on the raw interrupt status.
145
146
147
148
149
    while ((MAP_I2CMasterIntStatusEx(I2CA0_BASE, false) & (I2C_MASTER_INT_DATA | I2C_MASTER_INT_TIMEOUT)) == 0) {
        // wait for a few microseconds
        UtilsDelay(UTILS_DELAY_US_TO_COUNT(PYBI2C_TRANSAC_WAIT_DELAY_US));
        timeout -= PYBI2C_TRANSAC_WAIT_DELAY_US;
        if (timeout < 0) {
150
            // the peripheral is not responding, so stop
151
152
153
            return false;
        }
    }
154

155
    // Check for any errors in the transfer
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
    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;
}

176
STATIC bool pyb_i2c_write(byte devAddr, byte *data, uint len, bool stop) {
177
178
179
180
181
    // Set I2C codec slave address
    MAP_I2CMasterSlaveAddrSet(I2CA0_BASE, devAddr, false);
    // Write the first byte to the controller.
    MAP_I2CMasterDataPut(I2CA0_BASE, *data++);
    // Initiate the transfer.
182
    RET_IF_ERR(pyb_i2c_transaction(I2C_MASTER_CMD_BURST_SEND_START));
183
184
185
186
187
188

    // 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
189
        RET_IF_ERR(pyb_i2c_transaction(I2C_MASTER_CMD_BURST_SEND_CONT));
190
191
192
193
    }

    // If a stop bit is to be sent, send it.
    if (stop) {
194
        RET_IF_ERR(pyb_i2c_transaction(I2C_MASTER_CMD_BURST_SEND_STOP));
195
196
197
198
199
    }

    return true;
}

200
STATIC bool pyb_i2c_read(byte devAddr, byte *data, uint len) {
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
    uint cmd;

    // Set I2C codec slave address
    MAP_I2CMasterSlaveAddrSet(I2CA0_BASE, devAddr, true);

    // Check if its a single receive or burst receive
    if (len > 1) {
        // Initiate a burst receive sequence
        cmd = I2C_MASTER_CMD_BURST_RECEIVE_START;
    }
    else {
        // Configure for a single receive
        cmd = I2C_MASTER_CMD_SINGLE_RECEIVE;
    }

    // Initiate the transfer.
217
    RET_IF_ERR(pyb_i2c_transaction(cmd));
218
219
220
221
222
223
224
225
    // Decrement the count
    len--;
    // 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
226
            RET_IF_ERR(pyb_i2c_transaction(I2C_MASTER_CMD_BURST_RECEIVE_CONT));
227
228
229
        }
        else {
            // Complete the last reception
230
            RET_IF_ERR(pyb_i2c_transaction(I2C_MASTER_CMD_BURST_RECEIVE_FINISH));
231
232
233
234
235
236
237
238
239
        }
    }

    // Receive the last byte over I2C
    *data = MAP_I2CMasterDataGet(I2CA0_BASE);

    return true;
}

240
STATIC bool pyb_i2c_scan_device(byte devAddr) {
241
242
243
    // Set I2C codec slave address
    MAP_I2CMasterSlaveAddrSet(I2CA0_BASE, devAddr, true);
    // Initiate the transfer.
244
    RET_IF_ERR(pyb_i2c_transaction(I2C_MASTER_CMD_SINGLE_RECEIVE));
245
246
247
248
249
250
    // Since this is a hack, send the stop bit anyway
    MAP_I2CMasterControl(I2CA0_BASE, I2C_MASTER_CMD_BURST_SEND_ERROR_STOP);

    return true;
}

251
252
253
254
/******************************************************************************/
/* Micro Python bindings                                                      */
/******************************************************************************/

255
/// \method init(100000)
256
///
257
/// Initialise the I2C bus as a master with the given baudrate.
258
///
259
STATIC mp_obj_t pyb_i2c_init_helper(pyb_i2c_obj_t *self_in, mp_obj_t baudrate) {
260
261
    pyb_i2c_obj_t *self = self_in;

danicampora's avatar
danicampora committed
262
    // make sure the baudrate is between the valid range
263
    self->baudrate = MIN(MAX(mp_obj_get_int(baudrate), PYBI2C_MIN_BAUD_RATE_HZ), PYBI2C_MAX_BAUD_RATE_HZ);
264
265

    // init the I2C bus
266
267
268
269
    i2c_init(self);

    // register it with the sleep module
    pybsleep_add ((const mp_obj_t)self, (WakeUpCB_t)i2c_init);
270
271
272
273
274
275

    return mp_const_none;
}

/// \classmethod \constructor(bus, ...)
///
276
/// Construct an I2C object on the given bus.  `bus` can only be 0.
277
278
279
280
281
282
283
284
/// With no additional parameters, the I2C object is created but not
/// initialised (it has the settings from the last initialisation of
/// the bus, if any).  If extra arguments are given, the bus is initialised.
/// See `init` for parameters of initialisation.
STATIC mp_obj_t pyb_i2c_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
    // check arguments
    mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true);

285
286
    // setup the object
    pyb_i2c_obj_t *self = &pyb_i2c_obj;
287
    self->base.type = &pyb_i2c_type;
288

289
    if (n_args > 0) {
290
        // start the peripheral
291
        pyb_i2c_init_helper(self, *args);
292
293
294
295
296
    }

    return (mp_obj_t)self;
}

297
STATIC void pyb_i2c_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
298
    pyb_i2c_obj_t *self = self_in;
danicampora's avatar
danicampora committed
299
    if (self->baudrate > 0) {
300
        mp_printf(print, "<I2C0, I2C.MASTER, baudrate=%u>)", self->baudrate);
danicampora's avatar
danicampora committed
301
302
    }
    else {
303
        mp_print_str(print, "<I2C0>");
danicampora's avatar
danicampora committed
304
    }
305
306
}

307
308
STATIC mp_obj_t pyb_i2c_init(mp_obj_t self_in, mp_obj_t baudrate) {
    return pyb_i2c_init_helper(self_in, baudrate);
309
}
310
STATIC MP_DEFINE_CONST_FUN_OBJ_2(pyb_i2c_init_obj, pyb_i2c_init);
311
312
313
314

/// \method deinit()
/// Turn off the I2C bus.
STATIC mp_obj_t pyb_i2c_deinit(mp_obj_t self_in) {
315
316
317
318
319
    // 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;
320
321
    // unregister it with the sleep module
    pybsleep_remove ((const mp_obj_t)self_in);
322
323
324
325
326
327
328
329
    return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_i2c_deinit_obj, pyb_i2c_deinit);

/// \method is_ready(addr)
/// Check if an I2C device responds to the given address.  Only valid when in master mode.
STATIC mp_obj_t pyb_i2c_is_ready(mp_obj_t self_in, mp_obj_t i2c_addr_o) {
    mp_uint_t i2c_addr = mp_obj_get_int(i2c_addr_o);
330
331
    for (int i = 0; i < 7; i++) {
        if (pyb_i2c_scan_device(i2c_addr)) {
332
333
334
335
336
337
338
339
340
341
342
343
344
            return mp_const_true;
        }
    }
    return mp_const_false;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(pyb_i2c_is_ready_obj, pyb_i2c_is_ready);

/// \method scan()
/// Scan all I2C addresses from 0x01 to 0x7f and return a list of those that respond.
/// Only valid when in master mode.
STATIC mp_obj_t pyb_i2c_scan(mp_obj_t self_in) {
    mp_obj_t list = mp_obj_new_list(0, NULL);
    for (uint addr = 1; addr <= 127; addr++) {
345
346
        for (int i = 0; i < 7; i++) {
            if (pyb_i2c_scan_device(addr)) {
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
                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);

/// \method send(send, addr=0x00)
/// Send data on the bus:
///
///   - `send` is the data to send (an integer to send, or a buffer object)
///   - `addr` is the address to send to (only required in master mode)
/// Return value: `None`.
STATIC const mp_arg_t pyb_i2c_send_args[] = {
    { MP_QSTR_send,    MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
    { MP_QSTR_addr,                      MP_ARG_INT, {.u_int = 0} },
};
#define PYB_I2C_SEND_NUM_ARGS MP_ARRAY_SIZE(pyb_i2c_send_args)

STATIC mp_obj_t pyb_i2c_send(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
    // parse args
    mp_arg_val_t vals[PYB_I2C_SEND_NUM_ARGS];
    mp_arg_parse_all(n_args - 1, args + 1, kw_args, PYB_I2C_SEND_NUM_ARGS, pyb_i2c_send_args, vals);

    // get the buffer to send from
    mp_buffer_info_t bufinfo;
    uint8_t data[1];
    pyb_buf_get_for_send(vals[0].u_obj, &bufinfo, data);

    // send the data
380
    if (!pyb_i2c_write(vals[1].u_int, bufinfo.buf, bufinfo.len, true)) {
381
        nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_operation_failed));
382
383
384
385
386
387
    }

    return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_i2c_send_obj, 1, pyb_i2c_send);

388
/// \method recv(recv, addr=0x00)
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
///
/// Receive data on the bus:
///
///   - `recv` can be an integer, which is the number of bytes to receive,
///     or a mutable buffer, which will be filled with received bytes
///   - `addr` is the address to receive from (only required in master mode)
///
/// Return value: if `recv` is an integer then a new buffer of the bytes received,
/// otherwise the same buffer that was passed in to `recv`.
STATIC const mp_arg_t pyb_i2c_recv_args[] = {
    { MP_QSTR_recv,    MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
    { MP_QSTR_addr,                      MP_ARG_INT, {.u_int = 0} },
};
#define PYB_I2C_RECV_NUM_ARGS MP_ARRAY_SIZE(pyb_i2c_recv_args)

STATIC mp_obj_t pyb_i2c_recv(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
    // parse args
    mp_arg_val_t vals[PYB_I2C_RECV_NUM_ARGS];
    mp_arg_parse_all(n_args - 1, args + 1, kw_args, PYB_I2C_RECV_NUM_ARGS, pyb_i2c_recv_args, vals);

    // get the buffer to receive into
    vstr_t vstr;
    mp_obj_t o_ret = pyb_buf_get_for_recv(vals[0].u_obj, &vstr);

    // receive the data
414
    if (!pyb_i2c_read(vals[1].u_int, (byte *)vstr.buf, vstr.len)) {
415
        nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_operation_failed));
416
417
418
419
420
    }

    // return the received data
    if (o_ret != MP_OBJ_NULL) {
        return o_ret;
421
422
    }
    else {
423
424
425
426
427
        return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
    }
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_i2c_recv_obj, 1, pyb_i2c_recv);

428
/// \method mem_read(data, addr, memaddr, addr_size=8)
429
430
431
432
433
434
///
/// Read from the memory of an I2C device:
///
///   - `data` can be an integer or a buffer to read into
///   - `addr` is the I2C device address
///   - `memaddr` is the memory location within the I2C device
435
///   - `addr_size` selects the width of memaddr: 8 or 16 bits
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
///
/// Returns the read data.
/// This is only valid in master mode.
STATIC const mp_arg_t pyb_i2c_mem_read_args[] = {
    { MP_QSTR_data,      MP_ARG_REQUIRED  | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
    { MP_QSTR_addr,      MP_ARG_REQUIRED  | MP_ARG_INT, {.u_int = 0} },
    { MP_QSTR_memaddr,   MP_ARG_REQUIRED  | MP_ARG_INT, {.u_int = 0} },
    { MP_QSTR_addr_size, MP_ARG_KW_ONLY   | MP_ARG_INT, {.u_int = 8} },
};
#define PYB_I2C_MEM_READ_NUM_ARGS MP_ARRAY_SIZE(pyb_i2c_mem_read_args)

STATIC mp_obj_t pyb_i2c_mem_read(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
    // parse args
    mp_arg_val_t vals[PYB_I2C_MEM_READ_NUM_ARGS];
    mp_arg_parse_all(n_args - 1, args + 1, kw_args, PYB_I2C_MEM_READ_NUM_ARGS, pyb_i2c_mem_read_args, vals);

    // get the buffer to read into
    vstr_t vstr;
    mp_obj_t o_ret = pyb_buf_get_for_recv(vals[0].u_obj, &vstr);

    // get the addresses
    mp_uint_t i2c_addr = vals[1].u_int;
    mp_uint_t mem_addr = vals[2].u_int;
459
460
    // determine the width of mem_addr (1 or 2 bytes)
    mp_uint_t mem_addr_size = vals[3].u_int >> 3;
461
462

    // Write the register address to be read from.
463
    if (pyb_i2c_write (i2c_addr, (byte *)&mem_addr, mem_addr_size, false)) {
464
        // Read the specified length of data
465
        if (pyb_i2c_read (i2c_addr, (byte *)vstr.buf, vstr.len)) {
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
            // return the read data
            if (o_ret != MP_OBJ_NULL) {
                return o_ret;
            } else {
                return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
            }
        }
    }

    nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_operation_failed));

    return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_i2c_mem_read_obj, 1, pyb_i2c_mem_read);

481
/// \method mem_write(data, addr, memaddr, addr_size=8)
482
483
484
485
486
487
///
/// Write to the memory of an I2C device:
///
///   - `data` can be an integer or a buffer to write from
///   - `addr` is the I2C device address
///   - `memaddr` is the memory location within the I2C device
488
///   - `addr_size` selects the width of memaddr: 8 or 16 bits
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
///
/// Returns `None`.
/// This is only valid in master mode.
STATIC mp_obj_t pyb_i2c_mem_write(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
    // parse args (same as mem_read)
    mp_arg_val_t vals[PYB_I2C_MEM_READ_NUM_ARGS];
    mp_arg_parse_all(n_args - 1, args + 1, kw_args, PYB_I2C_MEM_READ_NUM_ARGS, pyb_i2c_mem_read_args, vals);

    // get the buffer to write from
    mp_buffer_info_t bufinfo;
    uint8_t data[1];
    pyb_buf_get_for_send(vals[0].u_obj, &bufinfo, data);

    // get the addresses
    mp_uint_t i2c_addr = vals[1].u_int;
    mp_uint_t mem_addr = vals[2].u_int;
505
506
    // determine the width of mem_addr (1 or 2 bytes)
    mp_uint_t mem_addr_size = vals[3].u_int >> 3;
507

danicampora's avatar
danicampora committed
508
    // Write the register address to write to.
509
    if (pyb_i2c_write (i2c_addr, (byte *)&mem_addr, mem_addr_size, false)) {
510
        // Write the specified length of data
511
        if (pyb_i2c_write (i2c_addr, bufinfo.buf, bufinfo.len, true)) {
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
            return mp_const_none;
        }
    }

    nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_operation_failed));

    return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_i2c_mem_write_obj, 1, pyb_i2c_mem_write);

STATIC const mp_map_elem_t pyb_i2c_locals_dict_table[] = {
    // instance methods
    { MP_OBJ_NEW_QSTR(MP_QSTR_init),            (mp_obj_t)&pyb_i2c_init_obj },
    { MP_OBJ_NEW_QSTR(MP_QSTR_deinit),          (mp_obj_t)&pyb_i2c_deinit_obj },
    { MP_OBJ_NEW_QSTR(MP_QSTR_is_ready),        (mp_obj_t)&pyb_i2c_is_ready_obj },
    { MP_OBJ_NEW_QSTR(MP_QSTR_scan),            (mp_obj_t)&pyb_i2c_scan_obj },
    { MP_OBJ_NEW_QSTR(MP_QSTR_send),            (mp_obj_t)&pyb_i2c_send_obj },
    { MP_OBJ_NEW_QSTR(MP_QSTR_recv),            (mp_obj_t)&pyb_i2c_recv_obj },
    { MP_OBJ_NEW_QSTR(MP_QSTR_mem_read),        (mp_obj_t)&pyb_i2c_mem_read_obj },
    { MP_OBJ_NEW_QSTR(MP_QSTR_mem_write),       (mp_obj_t)&pyb_i2c_mem_write_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,
};