Skip to content

Commit a86ddae

Browse files
authored
Merge pull request #16 from ganshun666/redbear-duo
Add I2C module
2 parents 3caaeba + c5e4c9a commit a86ddae

File tree

4 files changed

+310
-0
lines changed

4 files changed

+310
-0
lines changed

duo/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,7 @@ MP_SOURCE = \
203203
timer.c \
204204
uart.c \
205205
spi.c \
206+
i2c.c \
206207

207208
OBJ += $(PY_O)
208209
OBJ += $(addprefix $(BUILD)/,$(HAL_SOURCES:.c=.o))

duo/i2c.c

Lines changed: 278 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,278 @@
1+
/*
2+
* This file is part of the Micro Python project, http://micropython.org/
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2013, 2014 Damien P. George
7+
*
8+
* Permission is hereby granted, free of charge, to any person obtaining a copy
9+
* of this software and associated documentation files (the "Software"), to deal
10+
* in the Software without restriction, including without limitation the rights
11+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
* copies of the Software, and to permit persons to whom the Software is
13+
* furnished to do so, subject to the following conditions:
14+
*
15+
* The above copyright notice and this permission notice shall be included in
16+
* all copies or substantial portions of the Software.
17+
*
18+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24+
* THE SOFTWARE.
25+
*/
26+
27+
#include <stdio.h>
28+
#include <string.h>
29+
#include <stdlib.h>
30+
31+
#include "py/nlr.h"
32+
#include "py/runtime.h"
33+
#include "py/mphal.h"
34+
#include "pin.h"
35+
#include "genhdr/pins.h"
36+
#include "i2c.h"
37+
#include "wiring.h"
38+
39+
typedef struct _pyb_i2c_obj_t {
40+
mp_obj_base_t base;
41+
}pyb_i2c_obj_t;
42+
43+
void transfer_status(uint8_t num) {
44+
switch(num) {
45+
case 0 :
46+
printf("Success!\n");
47+
break;
48+
case 1 :
49+
printf("Error: Transfer data is too long, a buffer overflow!\n");
50+
break;
51+
case 2 :
52+
printf("Error: Send the address to receive NACK!\n");
53+
break;
54+
case 3 :
55+
printf("Error: Send the data to receive NACK!\n");
56+
break;
57+
case 4 :
58+
printf("Other error!\n");
59+
break;
60+
default :
61+
break;
62+
}
63+
64+
return;
65+
}
66+
67+
/******************************************************************************/
68+
/* Micro Python bindings */
69+
70+
/// \classmethod \constructor(bus, ...)
71+
///
72+
/// Construct an I2C object on the given bus. `bus` can be 1 or 2.
73+
/// With no additional parameters, the I2C object is created but not
74+
/// initialised (it has the settings from the last initialisation of
75+
/// the bus, if any). If extra arguments are given, the bus is initialised.
76+
/// See `init` for parameters of initialisation.
77+
78+
STATIC mp_obj_t pyb_i2c_make_new(void) {
79+
80+
// work out i2c bus
81+
pyb_i2c_obj_t *self = m_new0(pyb_i2c_obj_t, 1);
82+
self->base.type = &pyb_i2c_type;
83+
84+
i2c_begin();
85+
86+
return self;
87+
}
88+
89+
90+
STATIC mp_obj_t pyb_i2c_init(mp_obj_t shlf_in) {
91+
i2c_begin();
92+
93+
return mp_const_none;
94+
95+
}
96+
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_i2c_init_obj, 0, pyb_i2c_init);
97+
98+
/// \method deinit()
99+
/// Turn off the I2C bus.
100+
STATIC mp_obj_t pyb_i2c_deinit(mp_obj_t self_in) {
101+
i2c_end();
102+
103+
return mp_const_none;
104+
}
105+
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_i2c_deinit_obj, pyb_i2c_deinit);
106+
107+
STATIC mp_obj_t pyb_i2c_send_char(mp_obj_t self_in, mp_obj_t data, mp_obj_t addr) {
108+
pyb_i2c_obj_t *self = self_in;
109+
110+
i2c_beginTransmission((uint8_t)mp_obj_get_int(addr));
111+
i2c_writeOneByte((uint8_t)(mp_obj_get_int(data)));
112+
i2c_beginTransmission((uint8_t)mp_obj_get_int(addr));
113+
114+
return mp_const_none;
115+
}
116+
STATIC MP_DEFINE_CONST_FUN_OBJ_3(pyb_i2c_send_char_obj, pyb_i2c_send_char);
117+
118+
STATIC mp_obj_t pyb_i2c_recv_char(mp_obj_t self_in, mp_obj_t addr) {
119+
pyb_i2c_obj_t *self = self_in;
120+
121+
i2c_requestFrom((uint8_t)(mp_obj_get_int(addr)), 1, 1);
122+
return MP_OBJ_NEW_SMALL_INT(i2c_read());
123+
}
124+
STATIC MP_DEFINE_CONST_FUN_OBJ_2(pyb_i2c_recv_char_obj, pyb_i2c_recv_char);
125+
126+
/// \method send(send, addr=0x00, timeout=5000)
127+
/// Send data on the bus:
128+
///
129+
/// - `send` is the data to send (an integer to send, or a buffer object)
130+
/// - `addr` is the address to send to (only required in master mode)
131+
/// - `timeout` is the timeout in milliseconds to wait for the send
132+
///
133+
/// Return value: `None`.
134+
STATIC mp_obj_t pyb_i2c_send(mp_obj_t self_in, mp_obj_t send_buffer, mp_obj_t addr) {
135+
136+
i2c_beginTransmission((uint8_t)mp_obj_get_int(addr));
137+
138+
if(MP_OBJ_IS_STR(send_buffer)) {
139+
uint8_t *buf = mp_obj_str_get_str(send_buffer);
140+
141+
i2c_writeBytes(buf, strlen(buf));
142+
transfer_status(i2c_endTransmission(1));
143+
144+
return MP_OBJ_NEW_SMALL_INT(strlen(buf));
145+
146+
} else {
147+
int i = 0;
148+
mp_obj_list_t *buffer = MP_OBJ_TO_PTR(send_buffer);
149+
uint8_t *buf = NULL;
150+
buf = (char *)malloc(buffer->len);
151+
152+
for(; i < buffer->len; i++) {
153+
buf[i] = mp_obj_get_int(buffer->items[i]);
154+
}
155+
156+
i2c_writeBytes(buf, i);
157+
transfer_status(i2c_endTransmission(1));
158+
159+
return MP_OBJ_NEW_SMALL_INT(i);
160+
}
161+
}
162+
STATIC MP_DEFINE_CONST_FUN_OBJ_3(pyb_i2c_send_obj, pyb_i2c_send);
163+
164+
/// \method recv(recv, addr=0x00, timeout=5000)
165+
///
166+
/// Receive data on the bus:
167+
///
168+
/// - `recv` can be an integer, which is the number of bytes to receive,
169+
/// or a mutable buffer, which will be filled with received bytes
170+
/// - `addr` is the address to receive from (only required in master mode)
171+
/// - `timeout` is the timeout in milliseconds to wait for the receive
172+
///
173+
/// Return value: if `recv` is an integer then a new buffer of the bytes received,
174+
/// otherwise the same buffer that was passed in to `recv`.
175+
STATIC mp_obj_t pyb_i2c_recv(mp_uint_t n_args, const mp_obj_t *args) {
176+
int i = 0;
177+
char data = 0;
178+
i2c_requestFrom(((uint8_t)mp_obj_get_int(args[2])), (uint8_t)(mp_obj_get_int(args[3])), 1);
179+
180+
for(; i < mp_obj_get_int(args[3]); i++) {
181+
data = (char)i2c_read();
182+
mp_obj_list_append(args[1], MP_OBJ_NEW_SMALL_INT(data));
183+
184+
}
185+
186+
return mp_const_none;
187+
}
188+
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_i2c_recv_obj, 4, 4, pyb_i2c_recv);
189+
190+
STATIC mp_obj_t pyb_i2c_set_speed(mp_obj_t self_in, mp_obj_t clockSpeed) {
191+
pyb_i2c_obj_t *self = self_in;
192+
i2c_setSpeed(mp_obj_get_int(clockSpeed));
193+
194+
return mp_const_none;
195+
}
196+
STATIC MP_DEFINE_CONST_FUN_OBJ_2(pyb_i2c_set_speed_obj, pyb_i2c_set_speed);
197+
198+
STATIC mp_obj_t pyb_i2c_enable_DMA_mode(mp_obj_t self_in, mp_obj_t enableDMAMode) {
199+
pyb_i2c_obj_t *self = self_in;
200+
i2c_enableDMAMode(mp_obj_get_int(enableDMAMode));
201+
202+
return mp_const_none;
203+
}
204+
STATIC MP_DEFINE_CONST_FUN_OBJ_2(pyb_i2c_enable_DMA_mode_obj, pyb_i2c_enable_DMA_mode);
205+
206+
STATIC mp_obj_t pyb_i2c_stretch_clock(mp_obj_t self_in, mp_obj_t stretch) {
207+
pyb_i2c_obj_t *self = self_in;
208+
i2c_stretchClock(mp_obj_get_int(stretch));
209+
210+
return mp_const_none;
211+
}
212+
STATIC MP_DEFINE_CONST_FUN_OBJ_2(pyb_i2c_stretch_clock_obj, pyb_i2c_stretch_clock);
213+
214+
/// \method any()
215+
/// Return `True` if any characters waiting, else `False`.
216+
STATIC mp_obj_t pyb_i2c_any(mp_obj_t self_in) {
217+
pyb_i2c_obj_t *self = self_in;
218+
219+
return MP_OBJ_NEW_SMALL_INT(i2c_available());
220+
}
221+
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_i2c_any_obj, pyb_i2c_any);
222+
223+
STATIC mp_obj_t pyb_i2c_flush(mp_obj_t self_in) {
224+
pyb_i2c_obj_t *self = self_in;
225+
i2c_flush();
226+
printf("flush success!\n");
227+
228+
return mp_const_none;
229+
}
230+
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_i2c_flush_obj, pyb_i2c_flush);
231+
232+
STATIC mp_obj_t pyb_i2c_peek(mp_obj_t self_in) {
233+
pyb_i2c_obj_t *self = self_in;
234+
235+
return MP_OBJ_NEW_SMALL_INT(i2c_peek());
236+
}
237+
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_i2c_peek_obj, pyb_i2c_peek);
238+
239+
STATIC mp_obj_t pyb_i2c_isenable(mp_obj_t self_in) {
240+
pyb_i2c_obj_t *self = self_in;
241+
if (mp_obj_is_true(MP_OBJ_NEW_SMALL_INT(i2c_isEnabled()))) {
242+
return mp_const_true;
243+
} else {
244+
return mp_const_false;
245+
}
246+
247+
return mp_const_none;
248+
}
249+
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_i2c_isenable_obj, pyb_i2c_isenable);
250+
251+
STATIC const mp_map_elem_t pyb_i2c_locals_dict_table[] = {
252+
// instance methods
253+
{ MP_OBJ_NEW_QSTR(MP_QSTR_init), (mp_obj_t)&pyb_i2c_init_obj },
254+
{ MP_OBJ_NEW_QSTR(MP_QSTR_deinit), (mp_obj_t)&pyb_i2c_deinit_obj },
255+
256+
{ MP_OBJ_NEW_QSTR(MP_QSTR_send_char), (mp_obj_t)&pyb_i2c_send_char_obj },
257+
{ MP_OBJ_NEW_QSTR(MP_QSTR_recv_char), (mp_obj_t)&pyb_i2c_recv_char_obj },
258+
{ MP_OBJ_NEW_QSTR(MP_QSTR_send), (mp_obj_t)&pyb_i2c_send_obj },
259+
{ MP_OBJ_NEW_QSTR(MP_QSTR_recv), (mp_obj_t)&pyb_i2c_recv_obj },
260+
261+
{ MP_OBJ_NEW_QSTR(MP_QSTR_set_speed), (mp_obj_t)&pyb_i2c_set_speed_obj },
262+
{ MP_OBJ_NEW_QSTR(MP_QSTR_enable_DMA_mode), (mp_obj_t)&pyb_i2c_enable_DMA_mode_obj },
263+
{ MP_OBJ_NEW_QSTR(MP_QSTR_stretch_clock), (mp_obj_t)&pyb_i2c_stretch_clock_obj },
264+
{ MP_OBJ_NEW_QSTR(MP_QSTR_any), (mp_obj_t)&pyb_i2c_any_obj },
265+
{ MP_OBJ_NEW_QSTR(MP_QSTR_flush), (mp_obj_t)&pyb_i2c_flush_obj },
266+
{ MP_OBJ_NEW_QSTR(MP_QSTR_peek), (mp_obj_t)&pyb_i2c_peek_obj },
267+
{ MP_OBJ_NEW_QSTR(MP_QSTR_isenable), (mp_obj_t)&pyb_i2c_isenable_obj },
268+
269+
};
270+
271+
STATIC MP_DEFINE_CONST_DICT(pyb_i2c_locals_dict, pyb_i2c_locals_dict_table);
272+
273+
const mp_obj_type_t pyb_i2c_type = {
274+
{ &mp_type_type },
275+
.name = MP_QSTR_I2C,
276+
.make_new = pyb_i2c_make_new,
277+
.locals_dict = (mp_obj_t)&pyb_i2c_locals_dict,
278+
};

duo/i2c.h

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/*
2+
* This file is part of the Micro Python project, http://micropython.org/
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2013, 2014 Damien P. George
7+
*
8+
* Permission is hereby granted, free of charge, to any person obtaining a copy
9+
* of this software and associated documentation files (the "Software"), to deal
10+
* in the Software without restriction, including without limitation the rights
11+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
* copies of the Software, and to permit persons to whom the Software is
13+
* furnished to do so, subject to the following conditions:
14+
*
15+
* The above copyright notice and this permission notice shall be included in
16+
* all copies or substantial portions of the Software.
17+
*
18+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24+
* THE SOFTWARE.
25+
*/
26+
27+
// use this for OwnAddress1 to configure I2C in master mode
28+
extern const mp_obj_type_t pyb_i2c_type;
29+

duo/modpyb.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
#include "timer.h"
4545
#include "uart.h"
4646
#include "spi.h"
47+
#include "i2c.h"
4748

4849
/// \function millis()
4950
/// Returns the number of milliseconds since the board was last reset.
@@ -142,6 +143,7 @@ STATIC const mp_map_elem_t pyb_module_globals_table[] = {
142143
{ MP_OBJ_NEW_QSTR(MP_QSTR_Timer), (mp_obj_t)&pyb_timer_type }, \
143144
{ MP_OBJ_NEW_QSTR(MP_QSTR_UART), (mp_obj_t)&pyb_uart_type }, \
144145
{ MP_OBJ_NEW_QSTR(MP_QSTR_SPI), (mp_obj_t)&pyb_spi_type }, \
146+
{ MP_OBJ_NEW_QSTR(MP_QSTR_I2C), (mp_obj_t)&pyb_i2c_type }, \
145147
};
146148

147149

0 commit comments

Comments
 (0)