i2c.c 16.8 KB
Newer Older
1
2
3
#include <stdio.h>
#include <string.h>

4
#include "stm32f4xx_hal.h"
5
6
7
8
9
10
11

#include "nlr.h"
#include "misc.h"
#include "mpconfig.h"
#include "qstr.h"
#include "obj.h"
#include "runtime.h"
12
13
#include "pin.h"
#include "genhdr/pins.h"
14
#include "bufhelper.h"
15
16
#include "i2c.h"

17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
// Usage model:
//
// 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(1)                         # create on bus 1
//     i2c = I2C(1, I2C.MASTER)             # create and init as a master
//     i2c.deinit()                         # turn off the peripheral
//     i2c.init(I2C.MASTER, baudrate=20000) # init as a master
//     i2c.init(I2C.SLAVE, addr=0x42)       # init as a slave with given address
//
// 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
//
// You can specify a timeout (in ms):
//
//     i2c.send(b'123', timeout=2000)   # timout after 2 seconds
//
// A master must specify the recipient's address:
//
//     i2c.init(I2C.MASTER)
//     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:
//
//     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, timeout=1000)

62
63
64
#define PYB_I2C_MASTER (0)
#define PYB_I2C_SLAVE  (1)

65
#if MICROPY_HW_ENABLE_I2C1
66
I2C_HandleTypeDef I2CHandle1 = {.Instance = NULL};
67
#endif
68
I2C_HandleTypeDef I2CHandle2 = {.Instance = NULL};
69

70
71
void i2c_init0(void) {
    // reset the I2C1 handles
72
#if MICROPY_HW_ENABLE_I2C1
73
74
    memset(&I2CHandle1, 0, sizeof(I2C_HandleTypeDef));
    I2CHandle1.Instance = I2C1;
75
#endif
76
77
    memset(&I2CHandle2, 0, sizeof(I2C_HandleTypeDef));
    I2CHandle2.Instance = I2C2;
78
79
}

80
void i2c_init(I2C_HandleTypeDef *i2c) {
81
    // init the GPIO lines
82
    GPIO_InitTypeDef GPIO_InitStructure;
83
84
85
86
    GPIO_InitStructure.Mode = GPIO_MODE_AF_OD;
    GPIO_InitStructure.Speed = GPIO_SPEED_FAST;
    GPIO_InitStructure.Pull = GPIO_NOPULL; // have external pull-up resistors on both lines

87
    const pin_obj_t *pins[2];
88
    if (0) {
89
#if MICROPY_HW_ENABLE_I2C1
90
    } else if (i2c == &I2CHandle1) {
91
        // X-skin: X9=PB6=SCL, X10=PB7=SDA
92
93
        pins[0] = &pin_B6;
        pins[1] = &pin_B7;
94
95
96
        GPIO_InitStructure.Alternate = GPIO_AF4_I2C1;
        // enable the I2C clock
        __I2C1_CLK_ENABLE();
97
#endif
98
    } else if (i2c == &I2CHandle2) {
99
        // Y-skin: Y9=PB10=SCL, Y10=PB11=SDA
100
101
        pins[0] = &pin_B10;
        pins[1] = &pin_B11;
102
103
104
        GPIO_InitStructure.Alternate = GPIO_AF4_I2C2;
        // enable the I2C clock
        __I2C2_CLK_ENABLE();
105
106
107
    } else {
        // I2C does not exist for this board (shouldn't get here, should be checked by caller)
        return;
108
109
    }

110
111
112
113
114
115
    // init the GPIO lines
    for (uint i = 0; i < 2; i++) {
        GPIO_InitStructure.Pin = pins[i]->pin_mask;
        HAL_GPIO_Init(pins[i]->gpio, &GPIO_InitStructure);
    }

116
    // init the I2C device
117
    if (HAL_I2C_Init(i2c) != HAL_OK) {
118
        // init error
119
120
        // TODO should raise an exception, but this function is not necessarily going to be
        // called via Python, so may not be properly wrapped in an NLR handler
121
        printf("HardwareError: HAL_I2C_Init failed\n");
122
123
124
125
        return;
    }
}

126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
void i2c_deinit(I2C_HandleTypeDef *i2c) {
    HAL_I2C_DeInit(i2c);
    if (0) {
#if MICROPY_HW_ENABLE_I2C1
    } else if (i2c->Instance == I2C1) {
        __I2C1_FORCE_RESET();
        __I2C1_RELEASE_RESET();
        __I2C1_CLK_DISABLE();
#endif
    } else if (i2c->Instance == I2C2) {
        __I2C2_FORCE_RESET();
        __I2C2_RELEASE_RESET();
        __I2C2_CLK_DISABLE();
    }
}

142
143
144
145
146
/******************************************************************************/
/* Micro Python bindings                                                      */

typedef struct _pyb_i2c_obj_t {
    mp_obj_base_t base;
147
    I2C_HandleTypeDef *i2c;
148
149
} pyb_i2c_obj_t;

150
151
STATIC inline bool in_master_mode(pyb_i2c_obj_t *self) { return self->i2c->Init.OwnAddress1 == PYB_I2C_MASTER_ADDRESS; }

152
153
STATIC const pyb_i2c_obj_t pyb_i2c_obj[] = {
#if MICROPY_HW_ENABLE_I2C1
154
    {{&pyb_i2c_type}, &I2CHandle1},
155
156
157
#else
    {{&pyb_i2c_type}, NULL},
#endif
158
159
    {{&pyb_i2c_type}, &I2CHandle2}
};
160

161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
STATIC void pyb_i2c_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
    pyb_i2c_obj_t *self = self_in;

    uint i2c_num;
    if (self->i2c->Instance == I2C1) { i2c_num = 1; }
    else { i2c_num = 2; }

    if (self->i2c->State == HAL_I2C_STATE_RESET) {
        print(env, "I2C(%u)", i2c_num);
    } else {
        if (in_master_mode(self)) {
            print(env, "I2C(%u, I2C.MASTER, baudrate=%u)", i2c_num, self->i2c->Init.ClockSpeed);
        } else {
            print(env, "I2C(%u, I2C.SLAVE, addr=0x%02x)", i2c_num, (self->i2c->Instance->OAR1 >> 1) & 0x7f);
        }
    }
}

179
180
181
182
183
STATIC const mp_arg_t pyb_i2c_init_args[] = {
    { MP_QSTR_mode,     MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} },
    { MP_QSTR_addr,     MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0x12} },
    { MP_QSTR_baudrate, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 400000} },
    { MP_QSTR_gencall,  MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },
184
};
185
#define PYB_I2C_INIT_NUM_ARGS ARRAY_SIZE(pyb_i2c_init_args)
186
187
188

STATIC mp_obj_t pyb_i2c_init_helper(const pyb_i2c_obj_t *self, uint n_args, const mp_obj_t *args, mp_map_t *kw_args) {
    // parse args
189
190
    mp_arg_val_t vals[PYB_I2C_INIT_NUM_ARGS];
    mp_arg_parse_all(n_args, args, kw_args, PYB_I2C_INIT_NUM_ARGS, pyb_i2c_init_args, vals);
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215

    // set the I2C configuration values
    I2C_InitTypeDef *init = &self->i2c->Init;

    if (vals[0].u_int == PYB_I2C_MASTER) {
        // use a special address to indicate we are a master
        init->OwnAddress1 = PYB_I2C_MASTER_ADDRESS;
    } else {
        init->OwnAddress1 = (vals[1].u_int << 1) & 0xfe;
    }

    init->AddressingMode  = I2C_ADDRESSINGMODE_7BIT;
    init->ClockSpeed      = MIN(vals[2].u_int, 400000);
    init->DualAddressMode = I2C_DUALADDRESS_DISABLED;
    init->DutyCycle       = I2C_DUTYCYCLE_16_9;
    init->GeneralCallMode = vals[3].u_bool ? I2C_GENERALCALL_ENABLED : I2C_GENERALCALL_DISABLED;
    init->NoStretchMode   = I2C_NOSTRETCH_DISABLED;
    init->OwnAddress2     = 0xfe; // unused

    // init the I2C bus
    i2c_init(self->i2c);

    return mp_const_none;
}

216
217
STATIC mp_obj_t pyb_i2c_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) {
    // check arguments
218
    mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true);
219
220
221
222
223

    // get i2c number
    machine_int_t i2c_id = mp_obj_get_int(args[0]) - 1;

    // check i2c number
224
    if (!(0 <= i2c_id && i2c_id < ARRAY_SIZE(pyb_i2c_obj) && pyb_i2c_obj[i2c_id].i2c != NULL)) {
225
        nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "I2C bus %d does not exist", i2c_id + 1));
226
227
    }

228
    // get I2C object
229
    const pyb_i2c_obj_t *i2c_obj = &pyb_i2c_obj[i2c_id];
230

231
232
233
234
235
236
    if (n_args > 1 || n_kw > 0) {
        // start the peripheral
        mp_map_t kw_args;
        mp_map_init_fixed_table(&kw_args, n_kw, args + n_args);
        pyb_i2c_init_helper(i2c_obj, n_args - 1, args + 1, &kw_args);
    }
237

238
    return (mp_obj_t)i2c_obj;
239
240
}

241
242
243
244
245
246
247
248
249
250
251
252
STATIC mp_obj_t pyb_i2c_init(uint n_args, const mp_obj_t *args, mp_map_t *kw_args) {
    return pyb_i2c_init_helper(args[0], n_args - 1, 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) {
    pyb_i2c_obj_t *self = self_in;
    i2c_deinit(self->i2c);
    return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_i2c_deinit_obj, pyb_i2c_deinit);

253
// Check if an I2C device responds to the given address.
254
255
STATIC mp_obj_t pyb_i2c_is_ready(mp_obj_t self_in, mp_obj_t i2c_addr_o) {
    pyb_i2c_obj_t *self = self_in;
256
257
258
259
260

    if (!in_master_mode(self)) {
        nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "I2C must be a master"));
    }

261
262
263
    machine_uint_t i2c_addr = mp_obj_get_int(i2c_addr_o) << 1;

    for (int i = 0; i < 10; i++) {
264
        HAL_StatusTypeDef status = HAL_I2C_IsDeviceReady(self->i2c, i2c_addr, 10, 200);
265
266
267
268
269
270
271
272
273
        if (status == HAL_OK) {
            return mp_const_true;
        }
    }

    return mp_const_false;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(pyb_i2c_is_ready_obj, pyb_i2c_is_ready);

274
275
276
277
// Scan all I2C addresses from 0x01 to 0x7f and return a list of those that respond.
STATIC mp_obj_t pyb_i2c_scan(mp_obj_t self_in) {
    pyb_i2c_obj_t *self = self_in;

278
279
280
281
    if (!in_master_mode(self)) {
        nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "I2C must be a master"));
    }

282
283
284
285
    mp_obj_t list = mp_obj_new_list(0, NULL);

    for (uint addr = 1; addr <= 127; addr++) {
        for (int i = 0; i < 10; i++) {
286
            HAL_StatusTypeDef status = HAL_I2C_IsDeviceReady(self->i2c, addr << 1, 10, 200);
287
288
289
290
291
292
293
294
295
296
297
            if (status == HAL_OK) {
                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);

298
299
300
301
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 = PYB_I2C_MASTER_ADDRESS} },
    { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 5000} },
302
};
303
#define PYB_I2C_SEND_NUM_ARGS ARRAY_SIZE(pyb_i2c_send_args)
304

305
306
307
308
STATIC mp_obj_t pyb_i2c_send(uint n_args, const mp_obj_t *args, mp_map_t *kw_args) {
    pyb_i2c_obj_t *self = args[0];

    // parse args
309
310
    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);
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327

    // 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
    HAL_StatusTypeDef status;
    if (in_master_mode(self)) {
        if (vals[1].u_int == PYB_I2C_MASTER_ADDRESS) {
            nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "addr argument required"));
        }
        machine_uint_t i2c_addr = vals[1].u_int << 1;
        status = HAL_I2C_Master_Transmit(self->i2c, i2c_addr, bufinfo.buf, bufinfo.len, vals[2].u_int);
    } else {
        status = HAL_I2C_Slave_Transmit(self->i2c, bufinfo.buf, bufinfo.len, vals[2].u_int);
    }
328
329
330

    if (status != HAL_OK) {
        // TODO really need a HardwareError object, or something
331
        nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_Exception, "HAL_I2C_xxx_Transmit failed with code %d", status));
332
333
    }

334
    return mp_const_none;
335
}
336
337
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_i2c_send_obj, 1, pyb_i2c_send);

338
339
340
341
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 = PYB_I2C_MASTER_ADDRESS} },
    { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 5000} },
342
};
343
#define PYB_I2C_RECV_NUM_ARGS ARRAY_SIZE(pyb_i2c_recv_args)
344

345
346
STATIC mp_obj_t pyb_i2c_recv(uint n_args, const mp_obj_t *args, mp_map_t *kw_args) {
    pyb_i2c_obj_t *self = args[0];
347

348
    // parse args
349
350
    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);
351
352
353
354
355
356

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

    // receive the data
357
    HAL_StatusTypeDef status;
358
359
360
361
362
363
    if (in_master_mode(self)) {
        if (vals[1].u_int == PYB_I2C_MASTER_ADDRESS) {
            nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "addr argument required"));
        }
        machine_uint_t i2c_addr = vals[1].u_int << 1;
        status = HAL_I2C_Master_Receive(self->i2c, i2c_addr, bufinfo.buf, bufinfo.len, vals[2].u_int);
364
    } else {
365
        status = HAL_I2C_Slave_Receive(self->i2c, bufinfo.buf, bufinfo.len, vals[2].u_int);
366
367
368
369
    }

    if (status != HAL_OK) {
        // TODO really need a HardwareError object, or something
370
        nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_Exception, "HAL_I2C_xxx_Receive failed with code %d", status));
371
372
    }

373
374
375
376
377
378
    // return the received data
    if (o_ret == MP_OBJ_NULL) {
        return vals[0].u_obj;
    } else {
        return mp_obj_str_builder_end(o_ret);
    }
379
}
380
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_i2c_recv_obj, 1, pyb_i2c_recv);
381

382
383
384
385
386
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_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 5000} },
387
};
388
#define PYB_I2C_MEM_READ_NUM_ARGS ARRAY_SIZE(pyb_i2c_mem_read_args)
389

390
STATIC mp_obj_t pyb_i2c_mem_read(uint n_args, const mp_obj_t *args, mp_map_t *kw_args) {
391
392
    pyb_i2c_obj_t *self = args[0];

393
394
395
396
397
    if (!in_master_mode(self)) {
        nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "I2C must be a master"));
    }

    // parse args
398
399
    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);
400
401
402
403

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

405
406
407
408
409
    // get the addresses
    machine_uint_t i2c_addr = vals[1].u_int << 1;
    machine_uint_t mem_addr = vals[2].u_int;

    HAL_StatusTypeDef status = HAL_I2C_Mem_Read(self->i2c, i2c_addr, mem_addr, I2C_MEMADD_SIZE_8BIT, bufinfo.buf, bufinfo.len, vals[3].u_int);
410
411
412

    if (status != HAL_OK) {
        // TODO really need a HardwareError object, or something
413
        nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_Exception, "HAL_I2C_Mem_Read failed with code %d", status));
414
415
    }

416
417
418
419
420
421
    // return the read data
    if (o_ret == MP_OBJ_NULL) {
        return vals[0].u_obj;
    } else {
        return mp_obj_str_builder_end(o_ret);
    }
422
}
423
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_i2c_mem_read_obj, 1, pyb_i2c_mem_read);
424

425
STATIC mp_obj_t pyb_i2c_mem_write(uint n_args, const mp_obj_t *args, mp_map_t *kw_args) {
426
    pyb_i2c_obj_t *self = args[0];
427
428
429

    if (!in_master_mode(self)) {
        nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "I2C must be a master"));
430
431
    }

432
    // parse args (same as mem_read)
433
434
    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);
435
436
437
438
439
440
441
442
443
444
445

    // 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
    machine_uint_t i2c_addr = vals[1].u_int << 1;
    machine_uint_t mem_addr = vals[2].u_int;

    HAL_StatusTypeDef status = HAL_I2C_Mem_Write(self->i2c, i2c_addr, mem_addr, I2C_MEMADD_SIZE_8BIT, bufinfo.buf, bufinfo.len, vals[3].u_int);
446
447
448

    if (status != HAL_OK) {
        // TODO really need a HardwareError object, or something
449
        nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_Exception, "HAL_I2C_Mem_Write failed with code %d", status));
450
451
452
453
    }

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

456
STATIC const mp_map_elem_t pyb_i2c_locals_dict_table[] = {
457
458
459
    // 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 },
460
    { MP_OBJ_NEW_QSTR(MP_QSTR_is_ready), (mp_obj_t)&pyb_i2c_is_ready_obj },
461
    { MP_OBJ_NEW_QSTR(MP_QSTR_scan), (mp_obj_t)&pyb_i2c_scan_obj },
462
463
    { 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 },
464
465
    { 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 },
466
467
468
469

    // class constants
    { MP_OBJ_NEW_QSTR(MP_QSTR_MASTER),       MP_OBJ_NEW_SMALL_INT(PYB_I2C_MASTER) },
    { MP_OBJ_NEW_QSTR(MP_QSTR_SLAVE),        MP_OBJ_NEW_SMALL_INT(PYB_I2C_SLAVE) },
470
471
};

472
473
STATIC MP_DEFINE_CONST_DICT(pyb_i2c_locals_dict, pyb_i2c_locals_dict_table);

474
475
476
const mp_obj_type_t pyb_i2c_type = {
    { &mp_type_type },
    .name = MP_QSTR_I2C,
477
    .print = pyb_i2c_print,
478
    .make_new = pyb_i2c_make_new,
479
    .locals_dict = (mp_obj_t)&pyb_i2c_locals_dict,
480
};