Merge remote-tracking branch 'upstream/master' into nrf5_no_sdk

This commit is contained in:
Glenn Ruben Bakke 2017-05-18 23:23:21 +02:00
commit 4a7716f5dd
17 changed files with 204 additions and 67 deletions

View File

@ -150,11 +150,19 @@ The following methods manipulate individual pixels on the display.
.. method:: LCD160CR.get_line(x, y, buf)
Get a line of pixels into the given buffer.
Low-level method to get a line of pixels into the given buffer.
To read `n` pixels `buf` should be `2*n+1` bytes in length. The first byte
is a dummy byte and should be ignored, and subsequent bytes represent the
pixels in the line starting at coordinate `(x, y)`.
.. method:: LCD160CR.screen_dump(buf)
.. method:: LCD160CR.screen_dump(buf, x=0, y=0, w=None, h=None)
Dump the entire screen to the given buffer.
Dump the contents of the screen to the given buffer. The parameters `x` and `y`
specify the starting coordinate, and `w` and `h` the size of the region. If `w`
or `h` are `None` then they will take on their maximum values, set by the size
of the screen minus the given `x` and `y` values. `buf` should be large enough
to hold `2*w*h` bytes. If it's smaller then only the initial horizontal lines
will be stored.
.. method:: LCD160CR.screen_load(buf)

View File

@ -7,6 +7,32 @@
Functions
---------
.. function:: const(expr)
Used to declare that the expression is a constant so that the compile can
optimise it. The use of this function should be as follows::
from micropython import const
CONST_X = const(123)
CONST_Y = const(2 * CONST_X + 1)
Constants declared this way are still accessible as global variables from
outside the module they are declared in. On the other hand, if a constant
begins with an underscore then it is hidden, it is not available as a global
variable, and does not take up any memory during execution.
This `const` function is recognised directly by the MicroPython parser and is
provided as part of the `micropython` module mainly so that scripts can be
written which run under both CPython and MicroPython, by following the above
pattern.
.. function:: opt_level([level])
If `level` is given then this function sets the optimisation level for subsequent
compilation of scripts, and returns `None`. Otherwise it returns the current
optimisation level.
.. function:: alloc_emergency_exception_buf(size)
Allocate ``size`` bytes of RAM for the emergency exception buffer (a good
@ -35,3 +61,56 @@ Functions
The information that is printed is implementation dependent, but currently
includes the number of interned strings and the amount of RAM they use. In
verbose mode it prints out the names of all RAM-interned strings.
.. function:: stack_use()
Return an integer representing the current amount of stack that is being
used. The absolute value of this is not particularly useful, rather it
should be used to compute differences in stack usage at different points.
.. function:: heap_lock()
.. function:: heap_unlock()
Lock or unlock the heap. When locked no memory allocation can occur and a
`MemoryError` will be raised if any heap allocation is attempted.
These functions can be nested, ie `heap_lock()` can be called multiple times
in a row and the lock-depth will increase, and then `heap_unlock()` must be
called the same number of times to make the heap available again.
.. function:: kbd_intr(chr)
Set the character that will raise a `KeyboardInterrupt` exception. By
default this is set to 3 during script execution, corresponding to Ctrl-C.
Passing -1 to this function will disable capture of Ctrl-C, and passing 3
will restore it.
This function can be used to prevent the capturing of Ctrl-C on the
incoming stream of characters that is usually used for the REPL, in case
that stream is used for other purposes.
.. function:: schedule(fun, arg)
Schedule the function `fun` to be executed "very soon". The function
is passed the value `arg` as its single argument. "very soon" means that
the MicroPython runtime will do its best to execute the function at the
earliest possible time, given that it is also trying to be efficient, and
that the following conditions hold:
- A scheduled function will never preempt another scheduled function.
- Scheduled functions are always executed "between opcodes" which means
that all fundamental Python operations (such as appending to a list)
are guaranteed to be atomic.
- A given port may define "critical regions" within which scheduled
functions will never be executed. Functions may be scheduled within
a critical region but they will not be executed until that region
is exited. An example of a critical region is a preempting interrupt
handler (an IRQ).
A use for this function is to schedule a callback from a preempting IRQ.
Such an IRQ puts restrictions on the code that runs in the IRQ (for example
the heap may be locked) and scheduling a function to call later will lift
those restrictions.
There is a finite stack to hold the scheduled functions and `schedule`
will raise a `RuntimeError` if the stack is full.

View File

@ -48,7 +48,7 @@
{% endif %}
</p>
<p class="biglink">
<a class="biglink" href="{{ pathto("genrst/index") }}">Micropython Differences</a><br/>
<a class="biglink" href="{{ pathto("genrst/index") }}">MicroPython Differences</a><br/>
<span class="linkdescr">MicroPython operations which differ from CPython</span>
</p>
</td>

View File

@ -257,6 +257,7 @@ class LCD160CR:
def get_line(self, x, y, buf):
l = len(buf) // 2
self._fcmd2b('<BBBBB', 0x10, l, x, y)
l *= 2
t = 1000
while t:
self.i2c.readfrom_into(self.i2c_addr, self.buf1)
@ -267,21 +268,28 @@ class LCD160CR:
sleep_ms(1)
raise OSError(uerrno.ETIMEDOUT)
def screen_dump(self, buf):
line = bytearray(self.w + 1)
h = len(buf) // (2 * self.w)
if h > self.h:
h = self.h
for i in range(h):
ix = i * self.w * 2
self.get_line(0, i, line)
for j in range(1, len(line)):
buf[ix] = line[j]
ix += 1
self.get_line(self.w // 2, i, line)
for j in range(1, len(line)):
buf[ix] = line[j]
ix += 1
def screen_dump(self, buf, x=0, y=0, w=None, h=None):
if w is None:
w = self.w - x
if h is None:
h = self.h - y
if w <= 127:
line = bytearray(2 * w + 1)
line2 = None
else:
# split line if more than 254 bytes needed
buflen = (w + 1) // 2
line = bytearray(2 * buflen + 1)
line2 = memoryview(line)[:2 * (w - buflen) + 1]
for i in range(min(len(buf) // (2 * w), h)):
ix = i * w * 2
self.get_line(x, y + i, line)
buf[ix:ix + len(line) - 1] = memoryview(line)[1:]
ix += len(line) - 1
if line2:
self.get_line(x + buflen, y + i, line2)
buf[ix:ix + len(line2) - 1] = memoryview(line2)[1:]
ix += len(line2) - 1
def screen_load(self, buf):
l = self.w * self.h * 2+2

View File

@ -16,17 +16,25 @@ def show_adc(lcd, adc):
pass
for i in range(3):
lcd.set_text_color((825, 1625, 1600)[i], 0)
lcd.set_font(2)
lcd.set_pos(0, 100 + i * 16)
if lcd.h == 160:
lcd.set_font(2)
lcd.set_pos(0, 100 + i * 16)
else:
lcd.set_font(2, trans=1)
lcd.set_pos(0, lcd.h-60 + i * 16)
lcd.write('%4s: ' % ('TEMP', 'VBAT', 'VREF')[i])
if i > 0:
s = '%6.3fV' % data[i]
else:
s = '%5.1f°C' % data[i]
lcd.set_font(1, bold=0, scale=1)
if lcd.h == 160:
lcd.set_font(1, bold=0, scale=1)
else:
lcd.set_font(1, bold=0, scale=1, trans=1)
lcd.set_pos(45, lcd.h-60 + i * 16)
lcd.write(s)
def test_features(lcd):
def test_features(lcd, orient=lcd160cr.PORTRAIT):
# if we run on pyboard then use ADC and RTC features
try:
import pyb
@ -38,7 +46,7 @@ def test_features(lcd):
# set orientation and clear screen
lcd = get_lcd(lcd)
lcd.set_orient(lcd160cr.PORTRAIT)
lcd.set_orient(orient)
lcd.set_pen(0, 0)
lcd.erase()
@ -114,10 +122,10 @@ def test_features(lcd):
lcd.set_pos(2, 9)
lcd.write('%.2f fps' % (1000000 / dt))
def test_mandel(lcd):
def test_mandel(lcd, orient=lcd160cr.PORTRAIT):
# set orientation and clear screen
lcd = get_lcd(lcd)
lcd.set_orient(lcd160cr.PORTRAIT)
lcd.set_orient(orient)
lcd.set_pen(0, 0xffff)
lcd.erase()
@ -140,9 +148,11 @@ def test_mandel(lcd):
spi = lcd.fast_spi()
# draw the Mandelbrot set line-by-line
hh = ((h - 1) / 3.2)
ww = ((w - 1) / 2.4)
for v in range(h):
for u in range(w):
c = in_set((v / ((h - 1) / 3.2) - 2.3) + (u / ((w - 1) / 2.4) - 1.2) * 1j)
c = in_set((v / hh - 2.3) + (u / ww - 1.2) * 1j)
if c < 16:
rgb = c << 12 | c << 6
else:
@ -151,10 +161,10 @@ def test_mandel(lcd):
line[2 * u + 1] = rgb >> 8
spi.write(line)
def test_all(lcd):
def test_all(lcd, orient=lcd160cr.PORTRAIT):
lcd = get_lcd(lcd)
test_features(lcd)
test_mandel(lcd)
test_features(lcd, orient)
test_mandel(lcd, orient)
print('To run all tests: test_all(<lcd>)')
print('Individual tests are: test_features, test_mandel')

View File

@ -102,13 +102,13 @@ STATIC mp_obj_t esp_connect(mp_uint_t n_args, const mp_obj_t *args) {
if (n_args > 1) {
p = mp_obj_str_get_data(args[1], &len);
len = MIN(len, sizeof(config.ssid));
memcpy(config.ssid, p, len);
if (n_args > 2) {
p = mp_obj_str_get_data(args[2], &len);
} else {
p = "";
len = MIN(len, sizeof(config.password));
memcpy(config.password, p, len);
}
memcpy(config.password, p, len);
error_check(wifi_station_set_config(&config), "Cannot set STA config");
}

View File

@ -27,5 +27,5 @@ async def fade_in_out(LED):
loop = uasyncio.get_event_loop()
loop.create_task(fade_in_out(LED))
loop.call_later_ms_(800, fade_in_out(LED2))
loop.call_later_ms(800, fade_in_out(LED2))
loop.run_forever()

View File

@ -154,6 +154,10 @@ STATIC mp_obj_t range_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
o->start = self->start + slice.start * self->step;
o->stop = self->start + slice.stop * self->step;
o->step = slice.step * self->step;
if (slice.step < 0) {
// Negative slice steps have inclusive stop, so adjust for exclusive
o->stop -= self->step;
}
return MP_OBJ_FROM_PTR(o);
}
#endif

View File

@ -56,6 +56,9 @@ STATIC mp_uint_t stringio_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *er
(void)errcode;
mp_obj_stringio_t *o = MP_OBJ_TO_PTR(o_in);
check_stringio_is_open(o);
if (o->vstr->len <= o->pos) { // read to EOF, or seeked to EOF or beyond
return 0;
}
mp_uint_t remaining = o->vstr->len - o->pos;
if (size > remaining) {
size = remaining;

View File

@ -88,15 +88,22 @@ bool mp_seq_get_fast_slice_indexes(mp_uint_t len, mp_obj_t slice, mp_bound_slice
if (start < 0) {
start = len + start;
if (start < 0) {
start = 0;
if (indexes->step < 0) {
start = -1;
} else {
start = 0;
}
}
} else if (indexes->step > 0 && (mp_uint_t)start > len) {
start = len;
} else if (indexes->step < 0 && (mp_uint_t)start > len - 1) {
} else if (indexes->step < 0 && (mp_uint_t)start >= len) {
start = len - 1;
}
if (stop < 0) {
stop = len + stop;
if (stop < 0) {
stop = -1;
}
if (indexes->step < 0) {
stop += 1;
}

View File

@ -50,6 +50,7 @@
#include "rtc.h"
#include "i2c.h"
#include "spi.h"
#include "uart.h"
#include "wdt.h"
#if defined(MCU_SERIES_F4)
@ -553,13 +554,11 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_RTC), MP_ROM_PTR(&pyb_rtc_type) },
{ MP_ROM_QSTR(MP_QSTR_ADC), MP_ROM_PTR(&pyb_adc_type) },
#endif
// TODO: Per new API, I2C types below, if called with 1 arg (ID), should still
// initialize master mode on the peripheral.
{ MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&machine_i2c_type) },
{ MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&machine_hard_spi_type) },
{ MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&pyb_uart_type) },
{ MP_ROM_QSTR(MP_QSTR_WDT), MP_ROM_PTR(&pyb_wdt_type) },
#if 0
{ MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&pyb_uart_type) },
{ MP_ROM_QSTR(MP_QSTR_Timer), MP_ROM_PTR(&pyb_timer_type) },
{ MP_ROM_QSTR(MP_QSTR_HeartBeat), MP_ROM_PTR(&pyb_heartbeat_type) },
{ MP_ROM_QSTR(MP_QSTR_SD), MP_ROM_PTR(&pyb_sd_type) },

View File

@ -33,6 +33,10 @@ print(range(1, 4)[0:])
print(range(1, 4)[1:])
print(range(1, 4)[:-1])
print(range(7, -2, -4)[:])
print(range(1, 100, 5)[5:15:3])
print(range(1, 100, 5)[15:5:-3])
print(range(100, 1, -5)[5:15:3])
print(range(100, 1, -5)[15:5:-3])
# zero step
try:

View File

@ -26,3 +26,14 @@ print(x[-1:-1:-1])
print(x[-1:-2:-1])
print(x[-1:-11:-1])
print(x[-10:-11:-1])
print(x[:-15:-1])
# test negative indices that are out-of-bounds
print([][::-1])
print([1][::-1])
print([][0:-10:-1])
print([1][0:-10:-1])
print([][:-20:-1])
print([1][:-20:-1])
print([][-20::-1])
print([1][-20::-1])

View File

@ -4,6 +4,10 @@ try:
except ImportError:
import io
a = io.BytesIO(b"foobar")
a.seek(10)
print(a.read(10))
a = io.BytesIO()
print(a.seek(8))
a.write(b"123")

View File

@ -343,7 +343,7 @@ class RawCode:
print('#elif MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_C')
n = struct.unpack('<I', struct.pack('<f', self.objs[i]))[0]
n = ((n & ~0x3) | 2) + 0x80800000
print(' MP_ROM_INT(0x%08x),' % (n,))
print(' (mp_rom_obj_t)(0x%08x),' % (n,))
print('#else')
print('#error "MICROPY_OBJ_REPR_D not supported with floats in frozen mpy files"')
print('#endif')

View File

@ -62,6 +62,13 @@ static char heap[MICROPY_HEAP_SIZE];
void init_zephyr(void) {
// TODO: Make addresses configurable
#ifdef CONFIG_NETWORKING
if (net_if_get_default() == NULL) {
// If there's no default networking interface,
// there's nothing to configure.
return;
}
#endif
#ifdef CONFIG_NET_IPV4
static struct in_addr in4addr_my = {{{192, 0, 2, 1}}};
net_if_ipv4_addr_add(net_if_get_default(), &in4addr_my, NET_ADDR_MANUAL, 0);

View File

@ -52,7 +52,6 @@ typedef struct _socket_obj_t {
struct k_fifo recv_q;
struct k_fifo accept_q;
};
struct net_pkt *cur_pkt;
#define STATE_NEW 0
#define STATE_CONNECTING 1
@ -208,7 +207,6 @@ socket_obj_t *socket_new(void) {
socket_obj_t *socket = m_new_obj_with_finaliser(socket_obj_t);
socket->base.type = (mp_obj_t)&socket_type;
k_fifo_init(&socket->recv_q);
socket->cur_pkt = NULL;
socket->state = STATE_NEW;
return socket;
}
@ -393,24 +391,20 @@ STATIC mp_uint_t sock_read(mp_obj_t self_in, void *buf, mp_uint_t max_len, int *
do {
if (socket->cur_pkt == NULL) {
if (socket->state == STATE_PEER_CLOSED) {
return 0;
}
DEBUG_printf("TCP recv: no cur_pkt, getting\n");
struct net_pkt *pkt = k_fifo_get(&socket->recv_q, K_FOREVER);
if (pkt == NULL) {
DEBUG_printf("TCP recv: NULL return from fifo\n");
continue;
}
DEBUG_printf("TCP recv: new cur_pkt: %p\n", pkt);
socket->cur_pkt = pkt;
if (socket->state == STATE_PEER_CLOSED) {
return 0;
}
struct net_buf *frag = socket->cur_pkt->frags;
_k_fifo_wait_non_empty(&socket->recv_q, K_FOREVER);
struct net_pkt *pkt = _k_fifo_peek_head(&socket->recv_q);
if (pkt == NULL) {
DEBUG_printf("TCP recv: NULL return from fifo\n");
continue;
}
DEBUG_printf("TCP recv: cur_pkt: %p\n", pkt);
struct net_buf *frag = pkt->frags;
if (frag == NULL) {
printf("net_pkt has empty fragments on start!\n");
assert(0);
@ -428,15 +422,17 @@ STATIC mp_uint_t sock_read(mp_obj_t self_in, void *buf, mp_uint_t max_len, int *
if (recv_len != frag_len) {
net_buf_pull(frag, recv_len);
} else {
frag = net_pkt_frag_del(socket->cur_pkt, NULL, frag);
frag = net_pkt_frag_del(pkt, NULL, frag);
if (frag == NULL) {
DEBUG_printf("Finished processing pkt %p\n", socket->cur_pkt);
DEBUG_printf("Finished processing pkt %p\n", pkt);
// Drop head packet from queue
k_fifo_get(&socket->recv_q, K_NO_WAIT);
// If "sent" flag was set, it's last packet and we reached EOF
if (net_pkt_sent(socket->cur_pkt)) {
if (net_pkt_sent(pkt)) {
socket->state = STATE_PEER_CLOSED;
}
net_pkt_unref(socket->cur_pkt);
socket->cur_pkt = NULL;
net_pkt_unref(pkt);
}
}
// Keep repeating while we're getting empty fragments
@ -576,10 +572,7 @@ STATIC mp_obj_t mod_getaddrinfo(size_t n_args, const mp_obj_t *args) {
int status;
for (int i = 2; i--;) {
int type = (family != AF_INET6 ? DNS_QUERY_TYPE_A : DNS_QUERY_TYPE_AAAA);
status = dns_get_addr_info(host, type, NULL, dns_resolve_cb, &state, 3000);
if (status < 0) {
mp_raise_OSError(status);
}
RAISE_ERRNO(dns_get_addr_info(host, type, NULL, dns_resolve_cb, &state, 3000));
k_sem_take(&state.sem, K_FOREVER);
if (family != 0) {
break;