forked from xuos/xiuos
Ubiquitous/RT-Thread_Fusion_XiUOS:change name from RT_Thread to RT-Thread_Fusion_XiUOS
This commit is contained in:
@@ -0,0 +1,152 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2019 ChenYong (chenyong@rt-thread.com)
|
||||
*
|
||||
* 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 <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "py/nlr.h"
|
||||
#include "py/runtime.h"
|
||||
#include "modmachine.h"
|
||||
#include "mphalport.h"
|
||||
|
||||
#ifdef MICROPYTHON_USING_MACHINE_ADC
|
||||
|
||||
#include <rtthread.h>
|
||||
#include <drivers/adc.h>
|
||||
|
||||
extern const mp_obj_type_t machine_adc_type;
|
||||
|
||||
typedef struct _machine_adc_obj_t {
|
||||
mp_obj_base_t base;
|
||||
struct rt_adc_device *adc_device;
|
||||
uint8_t channel;
|
||||
uint8_t is_init;
|
||||
} machine_adc_obj_t;
|
||||
|
||||
STATIC void error_check(bool status, const char *msg) {
|
||||
if (!status) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, msg));
|
||||
}
|
||||
}
|
||||
|
||||
STATIC mp_obj_t machine_adc_make_new(const mp_obj_type_t *type,
|
||||
size_t n_args, size_t n_kw, const mp_obj_t *args) {
|
||||
// create ADC object from the given pin
|
||||
machine_adc_obj_t *self = m_new_obj(machine_adc_obj_t);
|
||||
struct rt_adc_device *adc_device = RT_NULL;
|
||||
char adc_dev_name[RT_NAME_MAX] = {0};
|
||||
rt_err_t result = RT_EOK;
|
||||
|
||||
// init machine adc object information
|
||||
self->channel = 0;
|
||||
self->is_init = RT_FALSE;
|
||||
self->base.type = &machine_adc_type;
|
||||
|
||||
mp_arg_check_num(n_args, n_kw, 1, 2, true);
|
||||
|
||||
// check input ADC device name or ID
|
||||
if (mp_obj_is_small_int(args[0])) {
|
||||
rt_snprintf(adc_dev_name, sizeof(adc_dev_name), "adc%d", mp_obj_get_int(args[0]));
|
||||
} else if (mp_obj_is_qstr(args[0])) {
|
||||
rt_strncpy(adc_dev_name, mp_obj_str_get_str(args[0]), RT_NAME_MAX);
|
||||
} else {
|
||||
error_check(0, "Input ADC device name or ID error.");
|
||||
}
|
||||
|
||||
adc_device = (struct rt_adc_device *) rt_device_find(adc_dev_name);
|
||||
if (adc_device == RT_NULL || adc_device->parent.type != RT_Device_Class_Miscellaneous) {
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError,
|
||||
"ADC(%s) don't exist", adc_dev_name));
|
||||
}
|
||||
self->adc_device = adc_device;
|
||||
|
||||
if (n_args == 2) {
|
||||
self->channel = mp_obj_get_int(args[1]);
|
||||
result = rt_adc_enable(self->adc_device, self->channel);
|
||||
error_check(result == RT_EOK, "ADC enable error");
|
||||
self->is_init = RT_TRUE;
|
||||
}
|
||||
|
||||
return MP_OBJ_FROM_PTR(self);
|
||||
}
|
||||
|
||||
STATIC mp_obj_t machine_adc_init(size_t n_args, const mp_obj_t *args) {
|
||||
machine_adc_obj_t *self = MP_OBJ_TO_PTR(args[0]);
|
||||
rt_err_t result = RT_EOK;
|
||||
|
||||
result = rt_adc_enable(self->adc_device, mp_obj_get_int(args[1]));
|
||||
error_check(result == RT_EOK, "ADC enable error");
|
||||
self->channel = mp_obj_get_int(args[1]);
|
||||
self->is_init = RT_TRUE;
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_adc_init_obj, 2, 2, machine_adc_init);
|
||||
|
||||
STATIC mp_obj_t machine_adc_deinit(mp_obj_t self_in) {
|
||||
machine_adc_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
rt_err_t result = RT_EOK;
|
||||
|
||||
if (self->is_init == RT_TRUE) {
|
||||
result = rt_adc_disable(self->adc_device, self->channel);
|
||||
error_check(result == RT_EOK, "ADC disable error");
|
||||
self->is_init = RT_FALSE;
|
||||
}
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_adc_deinit_obj, machine_adc_deinit);
|
||||
|
||||
STATIC mp_obj_t machine_adc_read(mp_obj_t self_in) {
|
||||
machine_adc_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
int tval = 0;
|
||||
|
||||
error_check(self->is_init == RT_TRUE, "ADC device uninitialized");
|
||||
|
||||
tval = rt_adc_read(self->adc_device, self->channel);
|
||||
return MP_OBJ_NEW_SMALL_INT(tval);
|
||||
}
|
||||
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_adc_read_obj, machine_adc_read);
|
||||
|
||||
STATIC const mp_rom_map_elem_t machine_adc_locals_dict_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_adc_init_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_adc_deinit_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&machine_adc_read_obj) },
|
||||
};
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(machine_adc_locals_dict,
|
||||
machine_adc_locals_dict_table);
|
||||
|
||||
const mp_obj_type_t machine_adc_type = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_ADC,
|
||||
.make_new = machine_adc_make_new,
|
||||
.locals_dict = (mp_obj_dict_t *) &machine_adc_locals_dict,
|
||||
};
|
||||
|
||||
#endif // MICROPYTHON_USING_MACHINE_adc
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2019 ChenYong (chenyong@rt-thread.com)
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef MICROPY_INCLUDED_MACHINE_ADC_H
|
||||
#define MICROPY_INCLUDED_MACHINE_ADC_H
|
||||
|
||||
#include "py/obj.h"
|
||||
#include <rtthread.h>
|
||||
|
||||
extern const mp_obj_type_t machine_adc_type;
|
||||
|
||||
#endif // MICROPY_INCLUDED_MACHINE_ADC_H
|
||||
@@ -0,0 +1,361 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 SummerGift <zhangyuan@rt-thread.com>
|
||||
*
|
||||
* 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 <rtdevice.h>
|
||||
|
||||
#include "py/runtime.h"
|
||||
#include "py/mphal.h"
|
||||
#include "py/mperrno.h"
|
||||
#include "extmod/machine_i2c.h"
|
||||
|
||||
#ifdef MICROPYTHON_USING_MACHINE_I2C
|
||||
|
||||
STATIC const mp_obj_type_t machine_hard_i2c_type;
|
||||
|
||||
STATIC const mp_arg_t machine_i2c_mem_allowed_args[] = {
|
||||
{ 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_arg, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
|
||||
{ MP_QSTR_addrsize, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 8} },
|
||||
};
|
||||
|
||||
typedef struct _machine_hard_i2c_obj_t {
|
||||
mp_obj_base_t base;
|
||||
struct rt_i2c_bus_device *i2c_bus;
|
||||
} machine_hard_i2c_obj_t;
|
||||
|
||||
#ifndef RT_USING_I2C
|
||||
#error "Please define the RT_USING_I2C on 'rtconfig.h'"
|
||||
#endif
|
||||
|
||||
STATIC void machine_hard_i2c_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
|
||||
machine_hard_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
mp_printf(print,"I2C(%s, timeout=%u)",
|
||||
self->i2c_bus->parent.parent.name,
|
||||
self->i2c_bus->timeout);
|
||||
return;
|
||||
}
|
||||
|
||||
STATIC int write_mem(mp_obj_t self_in, uint16_t addr, uint32_t memaddr, uint8_t addrsize, const uint8_t *buf, size_t len) {
|
||||
machine_hard_i2c_obj_t *self = (machine_hard_i2c_obj_t*)MP_OBJ_TO_PTR(self_in);
|
||||
|
||||
// Create buffer with memory address
|
||||
size_t memaddr_len = 0;
|
||||
uint8_t memaddr_buf[4];
|
||||
for (int16_t i = addrsize - 8; i >= 0; i -= 8) {
|
||||
memaddr_buf[memaddr_len++] = memaddr >> i;
|
||||
}
|
||||
|
||||
struct rt_i2c_msg msg[2];
|
||||
|
||||
msg[0].buf = memaddr_buf;
|
||||
msg[0].len = (addrsize + 7)/8;
|
||||
msg[0].flags = RT_I2C_WR;
|
||||
msg[0].addr = addr;
|
||||
|
||||
msg[1].buf = (rt_uint8_t*)buf;
|
||||
msg[1].len = len;
|
||||
msg[1].flags = RT_I2C_WR;
|
||||
msg[1].addr = addr;
|
||||
|
||||
if (rt_i2c_transfer(self->i2c_bus, msg, 2) != 2)
|
||||
return -MP_EIO;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
STATIC int read_mem(mp_obj_t self_in, uint16_t addr, uint32_t memaddr, uint8_t addrsize, uint8_t *buf, size_t len) {
|
||||
machine_hard_i2c_obj_t *self = (machine_hard_i2c_obj_t*)MP_OBJ_TO_PTR(self_in);
|
||||
uint8_t memaddr_buf[4];
|
||||
size_t memaddr_len = 0;
|
||||
for (int16_t i = addrsize - 8; i >= 0; i -= 8) {
|
||||
memaddr_buf[memaddr_len++] = memaddr >> i;
|
||||
}
|
||||
|
||||
struct rt_i2c_msg msg[2];
|
||||
|
||||
msg[0].buf = memaddr_buf;
|
||||
msg[0].len = (addrsize + 7)/8;
|
||||
msg[0].flags = RT_I2C_WR;
|
||||
msg[0].addr = addr;
|
||||
|
||||
msg[1].buf = buf;
|
||||
msg[1].len = len;
|
||||
msg[1].flags = RT_I2C_RD;
|
||||
msg[1].addr = addr;
|
||||
|
||||
if (rt_i2c_transfer(self->i2c_bus, msg, 2) != 2)
|
||||
return -MP_EIO;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
STATIC int mp_machine_i2c_readfrom(mp_obj_base_t *self_in, uint16_t addr, uint8_t *dest, size_t len, bool stop) {
|
||||
machine_hard_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
return rt_i2c_master_recv(self->i2c_bus, addr, 0, dest, len);
|
||||
}
|
||||
|
||||
STATIC int mp_machine_i2c_writeto(mp_obj_base_t *self_in, uint16_t addr, const uint8_t *src, size_t len, bool stop) {
|
||||
uint8_t buf[1] = {0};
|
||||
machine_hard_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
if (len == 0){
|
||||
len = 1;
|
||||
if (src == NULL){
|
||||
src = buf;
|
||||
}
|
||||
return !rt_i2c_master_send(self->i2c_bus, addr, 0, src, len);
|
||||
} else if (src == NULL){
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "buf must not NULL"));
|
||||
}
|
||||
return rt_i2c_master_send(self->i2c_bus, addr, 0, src, len);
|
||||
}
|
||||
|
||||
STATIC mp_obj_t machine_i2c_scan(mp_obj_t self_in) {
|
||||
mp_obj_base_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
mp_obj_t list = mp_obj_new_list(0, NULL);
|
||||
// 7-bit addresses 0b0000xxx and 0b1111xxx are reserved
|
||||
for (int addr = 0x08; addr < 0x78; ++addr) {
|
||||
int ret = mp_machine_i2c_writeto(self, addr, NULL, 0, true);
|
||||
if (ret == 0) {
|
||||
mp_obj_list_append(list, MP_OBJ_NEW_SMALL_INT(addr));
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_i2c_scan_obj, machine_i2c_scan);
|
||||
|
||||
STATIC mp_obj_t machine_i2c_readfrom(size_t n_args, const mp_obj_t *args) {
|
||||
mp_obj_base_t *self = (mp_obj_base_t*)MP_OBJ_TO_PTR(args[0]);
|
||||
mp_int_t addr = mp_obj_get_int(args[1]);
|
||||
vstr_t vstr;
|
||||
vstr_init_len(&vstr, mp_obj_get_int(args[2]));
|
||||
bool stop = (n_args == 3) ? true : mp_obj_is_true(args[3]);
|
||||
int ret = mp_machine_i2c_readfrom(self, addr, (uint8_t*)vstr.buf, vstr.len, stop);
|
||||
if (ret < 0) {
|
||||
mp_raise_OSError(-ret);
|
||||
}
|
||||
return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_i2c_readfrom_obj, 3, 4, machine_i2c_readfrom);
|
||||
|
||||
STATIC mp_obj_t machine_i2c_readfrom_into(size_t n_args, const mp_obj_t *args) {
|
||||
mp_obj_base_t *self = (mp_obj_base_t*)MP_OBJ_TO_PTR(args[0]);
|
||||
mp_int_t addr = mp_obj_get_int(args[1]);
|
||||
mp_buffer_info_t bufinfo;
|
||||
mp_get_buffer_raise(args[2], &bufinfo, MP_BUFFER_WRITE);
|
||||
bool stop = (n_args == 3) ? true : mp_obj_is_true(args[3]);
|
||||
int ret = mp_machine_i2c_readfrom(self, addr, bufinfo.buf, bufinfo.len, stop);
|
||||
if (ret < 0) {
|
||||
mp_raise_OSError(-ret);
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_i2c_readfrom_into_obj, 3, 4, machine_i2c_readfrom_into);
|
||||
|
||||
STATIC mp_obj_t machine_i2c_writeto(size_t n_args, const mp_obj_t *args) {
|
||||
mp_obj_base_t *self = (mp_obj_base_t*)MP_OBJ_TO_PTR(args[0]);
|
||||
mp_int_t addr = mp_obj_get_int(args[1]);
|
||||
mp_buffer_info_t bufinfo;
|
||||
mp_get_buffer_raise(args[2], &bufinfo, MP_BUFFER_READ);
|
||||
bool stop = (n_args == 3) ? true : mp_obj_is_true(args[3]);
|
||||
int ret = mp_machine_i2c_writeto(self, addr, bufinfo.buf, bufinfo.len, stop);
|
||||
if (ret < 0) {
|
||||
mp_raise_OSError(-ret);
|
||||
}
|
||||
// return number of acks received
|
||||
return MP_OBJ_NEW_SMALL_INT(ret);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_i2c_writeto_obj, 3, 4, machine_i2c_writeto);
|
||||
|
||||
STATIC mp_obj_t machine_i2c_writevto(size_t n_args, const mp_obj_t *args) {
|
||||
mp_obj_base_t *self = (mp_obj_base_t*)MP_OBJ_TO_PTR(args[0]);
|
||||
mp_int_t addr = mp_obj_get_int(args[1]);
|
||||
|
||||
// Get the list of data buffer(s) to write
|
||||
size_t nitems;
|
||||
const mp_obj_t *items;
|
||||
mp_obj_get_array(args[2], &nitems, (mp_obj_t**)&items);
|
||||
|
||||
// Get the stop argument
|
||||
bool stop = (n_args == 3) ? true : mp_obj_is_true(args[3]);
|
||||
|
||||
// Extract all buffer data, skipping zero-length buffers
|
||||
size_t alloc = nitems == 0 ? 1 : nitems;
|
||||
size_t nbufs = 0;
|
||||
struct rt_i2c_msg *bufs = mp_local_alloc(alloc * sizeof(struct rt_i2c_msg));
|
||||
for (; nitems--; ++items) {
|
||||
mp_buffer_info_t bufinfo;
|
||||
mp_get_buffer_raise(*items, &bufinfo, MP_BUFFER_READ);
|
||||
if (bufinfo.len > 0) {
|
||||
bufs[nbufs].addr = addr;
|
||||
bufs[nbufs].flags = RT_I2C_WR;
|
||||
bufs[nbufs].len = bufinfo.len;
|
||||
bufs[nbufs++].buf = bufinfo.buf;
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure there is at least one buffer, empty if needed
|
||||
if (nbufs == 0) {
|
||||
bufs[0].len = 0;
|
||||
bufs[0].buf = NULL;
|
||||
nbufs = 1;
|
||||
}
|
||||
|
||||
// Do the I2C transfer
|
||||
machine_hard_i2c_obj_t *i2c_p = (machine_hard_i2c_obj_t*)self;
|
||||
int ret = rt_i2c_transfer(i2c_p->i2c_bus, bufs, nbufs);
|
||||
mp_local_free(bufs);
|
||||
|
||||
if (ret < 0) {
|
||||
mp_raise_OSError(-ret);
|
||||
}
|
||||
|
||||
// Return number of acks received
|
||||
return MP_OBJ_NEW_SMALL_INT(ret);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_i2c_writevto_obj, 3, 4, machine_i2c_writevto);
|
||||
|
||||
STATIC mp_obj_t machine_i2c_readfrom_mem(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
enum { ARG_addr, ARG_memaddr, ARG_n, ARG_addrsize };
|
||||
mp_arg_val_t args[MP_ARRAY_SIZE(machine_i2c_mem_allowed_args)];
|
||||
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args,
|
||||
MP_ARRAY_SIZE(machine_i2c_mem_allowed_args), machine_i2c_mem_allowed_args, args);
|
||||
|
||||
// create the buffer to store data into
|
||||
vstr_t vstr;
|
||||
vstr_init_len(&vstr, mp_obj_get_int(args[ARG_n].u_obj));
|
||||
|
||||
// do the transfer
|
||||
int ret = read_mem(pos_args[0], args[ARG_addr].u_int, args[ARG_memaddr].u_int,
|
||||
args[ARG_addrsize].u_int, (uint8_t*)vstr.buf, vstr.len);
|
||||
if (ret < 0) {
|
||||
mp_raise_OSError(-ret);
|
||||
}
|
||||
|
||||
return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_i2c_readfrom_mem_obj, 1, machine_i2c_readfrom_mem);
|
||||
|
||||
STATIC mp_obj_t machine_i2c_readfrom_mem_into(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
enum { ARG_addr, ARG_memaddr, ARG_buf, ARG_addrsize };
|
||||
mp_arg_val_t args[MP_ARRAY_SIZE(machine_i2c_mem_allowed_args)];
|
||||
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args,
|
||||
MP_ARRAY_SIZE(machine_i2c_mem_allowed_args), machine_i2c_mem_allowed_args, args);
|
||||
|
||||
// get the buffer to store data into
|
||||
mp_buffer_info_t bufinfo;
|
||||
mp_get_buffer_raise(args[ARG_buf].u_obj, &bufinfo, MP_BUFFER_WRITE);
|
||||
|
||||
// do the transfer
|
||||
int ret = read_mem(pos_args[0], args[ARG_addr].u_int, args[ARG_memaddr].u_int,
|
||||
args[ARG_addrsize].u_int, bufinfo.buf, bufinfo.len);
|
||||
if (ret < 0) {
|
||||
mp_raise_OSError(-ret);
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_i2c_readfrom_mem_into_obj, 1, machine_i2c_readfrom_mem_into);
|
||||
|
||||
STATIC mp_obj_t machine_i2c_writeto_mem(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
enum { ARG_addr, ARG_memaddr, ARG_buf, ARG_addrsize };
|
||||
mp_arg_val_t args[MP_ARRAY_SIZE(machine_i2c_mem_allowed_args)];
|
||||
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args,
|
||||
MP_ARRAY_SIZE(machine_i2c_mem_allowed_args), machine_i2c_mem_allowed_args, args);
|
||||
|
||||
// get the buffer to write the data from
|
||||
mp_buffer_info_t bufinfo;
|
||||
mp_get_buffer_raise(args[ARG_buf].u_obj, &bufinfo, MP_BUFFER_READ);
|
||||
|
||||
// do the transfer
|
||||
int ret = write_mem(pos_args[0], args[ARG_addr].u_int, args[ARG_memaddr].u_int,
|
||||
args[ARG_addrsize].u_int, bufinfo.buf, bufinfo.len);
|
||||
if (ret < 0) {
|
||||
mp_raise_OSError(-ret);
|
||||
}
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_i2c_writeto_mem_obj, 1, machine_i2c_writeto_mem);
|
||||
|
||||
STATIC const mp_rom_map_elem_t machine_i2c_locals_dict_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR_scan), MP_ROM_PTR(&machine_i2c_scan_obj) },
|
||||
|
||||
// standard bus operations
|
||||
{ MP_ROM_QSTR(MP_QSTR_readfrom), MP_ROM_PTR(&machine_i2c_readfrom_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_readfrom_into), MP_ROM_PTR(&machine_i2c_readfrom_into_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_writeto), MP_ROM_PTR(&machine_i2c_writeto_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_writevto), MP_ROM_PTR(&machine_i2c_writevto_obj) },
|
||||
|
||||
// memory operations
|
||||
{ MP_ROM_QSTR(MP_QSTR_readfrom_mem), MP_ROM_PTR(&machine_i2c_readfrom_mem_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_readfrom_mem_into), MP_ROM_PTR(&machine_i2c_readfrom_mem_into_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_writeto_mem), MP_ROM_PTR(&machine_i2c_writeto_mem_obj) },
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
/* MicroPython bindings for machine API */
|
||||
|
||||
mp_obj_t machine_hard_i2c_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
|
||||
char iic_device[RT_NAME_MAX];
|
||||
|
||||
snprintf(iic_device, sizeof(iic_device), "i2c%d", mp_obj_get_int(all_args[0]));
|
||||
struct rt_i2c_bus_device *i2c_bus = rt_i2c_bus_device_find(iic_device);
|
||||
|
||||
if (i2c_bus == RT_NULL) {
|
||||
mp_printf(&mp_plat_print, "can't find %s device\r\n", iic_device);
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "I2C(%s) doesn't exist", iic_device));
|
||||
}
|
||||
|
||||
// create new hard I2C object
|
||||
machine_hard_i2c_obj_t *self = m_new_obj(machine_hard_i2c_obj_t);
|
||||
self->base.type = &machine_hard_i2c_type;
|
||||
self->i2c_bus = i2c_bus;
|
||||
return (mp_obj_t) self;
|
||||
}
|
||||
|
||||
MP_DEFINE_CONST_DICT(mp_machine_hard_i2c_locals_dict, machine_i2c_locals_dict_table);
|
||||
|
||||
STATIC const mp_machine_i2c_p_t machine_hard_i2c_p = {
|
||||
.start = NULL,
|
||||
.stop = NULL,
|
||||
.read = NULL,
|
||||
.write = NULL,
|
||||
.transfer = NULL,
|
||||
.transfer_single = NULL,
|
||||
};
|
||||
|
||||
STATIC const mp_obj_type_t machine_hard_i2c_type = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_I2C,
|
||||
.print = machine_hard_i2c_print,
|
||||
.make_new = machine_hard_i2c_make_new,
|
||||
.protocol = &machine_hard_i2c_p,
|
||||
.locals_dict = (mp_obj_dict_t*)&mp_machine_hard_i2c_locals_dict,
|
||||
};
|
||||
|
||||
#endif // MICROPYTHON_USING_MACHINE_I2C
|
||||
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018 SummerGift <zhangyuan@rt-thread.com>
|
||||
*
|
||||
* 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 <rtdevice.h>
|
||||
|
||||
#include "py/runtime.h"
|
||||
#include "py/mphal.h"
|
||||
#include "extmod/machine_spi.h"
|
||||
|
||||
#ifdef MICROPYTHON_USING_MACHINE_SPI
|
||||
|
||||
#ifndef RT_USING_SPI
|
||||
#error "Please define the RT_USING_SPI on 'rtconfig.h'"
|
||||
#endif
|
||||
|
||||
STATIC const mp_obj_type_t machine_hard_spi_type;
|
||||
|
||||
typedef struct _machine_hard_spi_obj_t {
|
||||
mp_obj_base_t base;
|
||||
struct rt_spi_device *spi_device;
|
||||
} machine_hard_spi_obj_t;
|
||||
|
||||
STATIC void machine_hard_spi_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
|
||||
machine_hard_spi_obj_t *self = (machine_hard_spi_obj_t*)self_in;
|
||||
mp_printf(print,"SPI(device port : %s)",self->spi_device->parent.parent.name);
|
||||
}
|
||||
|
||||
mp_obj_t machine_hard_spi_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
|
||||
char spi_dev_name[RT_NAME_MAX];
|
||||
|
||||
snprintf(spi_dev_name, sizeof(spi_dev_name), "spi%d", mp_obj_get_int(all_args[0]));
|
||||
|
||||
struct rt_spi_device *rt_spi_device = (struct rt_spi_device *) rt_device_find(spi_dev_name);
|
||||
if (rt_spi_device == RT_NULL || rt_spi_device->parent.type != RT_Device_Class_SPIDevice) {
|
||||
mp_printf(&mp_plat_print, "ERROR: SPI device %s not found!\n", spi_dev_name);
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "SPI(%s) doesn't exist", spi_dev_name));
|
||||
}
|
||||
|
||||
// create new hard SPI object
|
||||
machine_hard_spi_obj_t *self = m_new_obj(machine_hard_spi_obj_t);
|
||||
self->base.type = &machine_hard_spi_type;
|
||||
self->spi_device = rt_spi_device;
|
||||
return (mp_obj_t) self;
|
||||
}
|
||||
|
||||
//SPI.init( baudrate=100000, polarity=0, phase=0, bits=8, firstbit=SPI.MSB/LSB )
|
||||
STATIC void machine_hard_spi_init(mp_obj_base_t *self_in, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
machine_hard_spi_obj_t *self = (machine_hard_spi_obj_t*)self_in;
|
||||
rt_uint8_t mode = 0;
|
||||
int baudrate = mp_obj_get_int(pos_args[0]);
|
||||
int polarity = mp_obj_get_int(pos_args[1]);
|
||||
int phase = mp_obj_get_int(pos_args[2]);
|
||||
int bits = mp_obj_get_int(pos_args[3]);
|
||||
int firstbit = mp_obj_get_int(pos_args[4]);
|
||||
|
||||
if(!polarity && !phase)
|
||||
{
|
||||
mode = RT_SPI_MODE_0;
|
||||
}
|
||||
|
||||
if(!polarity && phase)
|
||||
{
|
||||
mode = RT_SPI_MODE_1;
|
||||
}
|
||||
|
||||
if(polarity && !phase)
|
||||
{
|
||||
mode = RT_SPI_MODE_2;
|
||||
}
|
||||
|
||||
if(polarity && phase)
|
||||
{
|
||||
mode = RT_SPI_MODE_3;
|
||||
}
|
||||
|
||||
if(firstbit)
|
||||
{
|
||||
mode |= RT_SPI_MSB;
|
||||
} else {
|
||||
mode |= RT_SPI_LSB;
|
||||
}
|
||||
|
||||
/* config spi */
|
||||
{
|
||||
struct rt_spi_configuration cfg;
|
||||
cfg.data_width = bits;
|
||||
cfg.mode = mode;
|
||||
cfg.max_hz = baudrate;
|
||||
rt_spi_configure(self->spi_device, &cfg);
|
||||
}
|
||||
}
|
||||
|
||||
STATIC void machine_hard_spi_transfer(mp_obj_base_t *self_in, size_t len, const uint8_t *src, uint8_t *dest) {
|
||||
machine_hard_spi_obj_t *self = (machine_hard_spi_obj_t*)self_in;
|
||||
|
||||
if (src && dest) {
|
||||
rt_spi_send_then_recv(self->spi_device, src, len, dest, len);
|
||||
} else if (src) {
|
||||
rt_spi_send(self->spi_device, src, len);
|
||||
} else {
|
||||
rt_spi_recv(self->spi_device, dest, len);
|
||||
}
|
||||
}
|
||||
|
||||
STATIC const mp_machine_spi_p_t machine_hard_spi_p = {
|
||||
.init = machine_hard_spi_init,
|
||||
.deinit = NULL,
|
||||
.transfer = machine_hard_spi_transfer,
|
||||
};
|
||||
|
||||
STATIC const mp_obj_type_t machine_hard_spi_type = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_SPI,
|
||||
.print = machine_hard_spi_print,
|
||||
.make_new = machine_hard_spi_make_new,
|
||||
.protocol = &machine_hard_spi_p,
|
||||
.locals_dict = (mp_obj_t)&mp_machine_spi_locals_dict,
|
||||
};
|
||||
|
||||
#endif // MICROPYTHON_USING_MACHINE_SPI
|
||||
|
||||
@@ -0,0 +1,356 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2019 SummerGift <SummerGift@qq.com>
|
||||
*
|
||||
* 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/mphal.h"
|
||||
#include "py/runtime.h"
|
||||
#include "py/mperrno.h"
|
||||
|
||||
#if MICROPY_PY_MACHINE_LCD
|
||||
#include <dfs_posix.h>
|
||||
#include "machine_lcd.h"
|
||||
#include <drv_lcd.h>
|
||||
|
||||
#define MAX_CO (2400 - 1)
|
||||
|
||||
typedef struct _machine_lcd_obj_t {
|
||||
mp_obj_base_t base;
|
||||
} machine_lcd_obj_t;
|
||||
|
||||
STATIC void error_check(bool status, const char *msg) {
|
||||
if (!status) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, msg));
|
||||
}
|
||||
}
|
||||
|
||||
/// \classmethod \constructor(skin_position)
|
||||
///
|
||||
/// Construct an LCD object.
|
||||
STATIC mp_obj_t machine_lcd_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
|
||||
// check arguments
|
||||
mp_arg_check_num(n_args, n_kw, 0, 0, false);
|
||||
|
||||
// create lcd object
|
||||
machine_lcd_obj_t *lcd = m_new_obj(machine_lcd_obj_t);
|
||||
lcd->base.type = &machine_lcd_type;
|
||||
|
||||
return MP_OBJ_FROM_PTR(lcd);
|
||||
}
|
||||
|
||||
/// \method light(value)
|
||||
///
|
||||
/// Turn the backlight on/off. True or 1 turns it on, False or 0 turns it off.
|
||||
STATIC mp_obj_t machine_lcd_light(mp_obj_t self_in, mp_obj_t value) {
|
||||
if (mp_obj_is_true(value)) {
|
||||
lcd_display_on(); // set pin high to turn backlight on
|
||||
} else {
|
||||
lcd_display_off();// set pin low to turn backlight off
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(machine_lcd_light_obj, machine_lcd_light);
|
||||
|
||||
/// \method fill(colour)
|
||||
///
|
||||
/// Fill the screen with the given colour.
|
||||
///
|
||||
STATIC mp_obj_t machine_lcd_fill(mp_obj_t self_in, mp_obj_t col_in) {
|
||||
int col = mp_obj_get_int(col_in);
|
||||
lcd_clear(col);
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(machine_lcd_fill_obj, machine_lcd_fill);
|
||||
|
||||
/// \method pixel(x, y, colour)
|
||||
///
|
||||
/// Set the pixel at `(x, y)` to the given colour.
|
||||
///
|
||||
STATIC mp_obj_t machine_lcd_pixel(size_t n_args, const mp_obj_t *args) {
|
||||
int x = mp_obj_get_int(args[1]);
|
||||
int y = mp_obj_get_int(args[2]);
|
||||
|
||||
error_check((x >= 0 && x <= MAX_CO) && (y >= 0 && y <= MAX_CO) , "The min/max X/Y coordinates is 0/239");
|
||||
|
||||
int col = mp_obj_get_int(args[3]);
|
||||
lcd_draw_point_color(x, y, col);
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_lcd_pixel_obj, 4, 4, machine_lcd_pixel);
|
||||
|
||||
/// \method text(str, x, y, size)
|
||||
///
|
||||
/// Draw the given text to the position `(x, y)` using the given size (16 24 32).
|
||||
///
|
||||
STATIC mp_obj_t machine_lcd_text(size_t n_args, const mp_obj_t *args) {
|
||||
size_t len;
|
||||
const char *data = mp_obj_str_get_data(args[1], &len);
|
||||
int x = mp_obj_get_int(args[2]);
|
||||
int y = mp_obj_get_int(args[3]);
|
||||
int size = mp_obj_get_int(args[4]);
|
||||
|
||||
error_check((x >= 0 && x <= MAX_CO) && (y >= 0 && y <= MAX_CO) , "The min/max X/Y coordinates is 0/239");
|
||||
|
||||
error_check(size == 16 || size == 24 || size == 32, "lcd only support font size 16 24 32");
|
||||
|
||||
lcd_show_string(x, y, size, data);
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_lcd_text_obj, 5, 5, machine_lcd_text);
|
||||
|
||||
/// \method line(x1, y1, x2, y2)
|
||||
///
|
||||
/// display a line on the lcd, from (x1, y1) to (x2, y2).
|
||||
///
|
||||
STATIC mp_obj_t machine_lcd_line(size_t n_args, const mp_obj_t *args) {
|
||||
int x1 = mp_obj_get_int(args[1]);
|
||||
int y1 = mp_obj_get_int(args[2]);
|
||||
int x2 = mp_obj_get_int(args[3]);
|
||||
int y2 = mp_obj_get_int(args[4]);
|
||||
|
||||
error_check((x1 >= 0 && x1 <= MAX_CO) && (y1 >= 0 && y1 <= MAX_CO) , "The min/max X/Y coordinates is 0/239");
|
||||
error_check((x2 >= 0 && x2 <= MAX_CO) && (y2 >= 0 && y2 <= MAX_CO) , "The min/max X/Y coordinates is 0/239");
|
||||
|
||||
lcd_draw_line(x1, y1, x2, y2);
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_lcd_line_obj, 5, 5, machine_lcd_line);
|
||||
|
||||
/// \method rectangle(x1, y1, x2, y2)
|
||||
///
|
||||
/// display a rectangle on the lcd, from (x1, y1) to (x2, y2).
|
||||
///
|
||||
STATIC mp_obj_t machine_lcd_rectangle(size_t n_args, const mp_obj_t *args) {
|
||||
int x1 = mp_obj_get_int(args[1]);
|
||||
int y1 = mp_obj_get_int(args[2]);
|
||||
int x2 = mp_obj_get_int(args[3]);
|
||||
int y2 = mp_obj_get_int(args[4]);
|
||||
|
||||
error_check((x1 >= 0 && x1 <= MAX_CO) && (y1 >= 0 && y1 <= MAX_CO) , "The min/max X/Y coordinates is 0/239");
|
||||
error_check((x2 >= 0 && x2 <= MAX_CO) && (y2 >= 0 && y2 <= MAX_CO) , "The min/max X/Y coordinates is 0/239");
|
||||
|
||||
lcd_draw_rectangle(x1, y1, x2, y2);
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_lcd_rectangle_obj, 5, 5, machine_lcd_rectangle);
|
||||
|
||||
/// \method circle(x1, y1, r)
|
||||
///
|
||||
/// display a circle on the lcd, center(x1, y1) R = r.
|
||||
///
|
||||
STATIC mp_obj_t machine_lcd_circle(size_t n_args, const mp_obj_t *args) {
|
||||
int x1 = mp_obj_get_int(args[1]);
|
||||
int y1 = mp_obj_get_int(args[2]);
|
||||
int r = mp_obj_get_int(args[3]);
|
||||
|
||||
error_check((x1 >= 0 && x1 <= MAX_CO) && (y1 >= 0 && y1 <= MAX_CO) , "The min/max X/Y coordinates is 0/239");
|
||||
|
||||
lcd_draw_circle(x1, y1, r);
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_lcd_circle_obj, 4, 4, machine_lcd_circle);
|
||||
|
||||
/// \method set_color(back, fore)
|
||||
///
|
||||
/// Set background color and foreground color.
|
||||
///
|
||||
STATIC mp_obj_t machine_lcd_set_color(size_t n_args, const mp_obj_t *args) {
|
||||
rt_uint16_t back = mp_obj_get_int(args[1]);
|
||||
rt_uint16_t fore = mp_obj_get_int(args[2]);
|
||||
|
||||
lcd_set_color(back, fore);
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_lcd_set_color_obj, 3, 3, machine_lcd_set_color);
|
||||
|
||||
/// \method show_image array
|
||||
///
|
||||
/// display the image on the lcd..
|
||||
/// @param x x position
|
||||
/// @param y y position
|
||||
/// @param length length of image
|
||||
/// @param wide wide of image
|
||||
/// @param p image_array
|
||||
STATIC mp_obj_t machine_lcd_show_image(size_t n_args, const mp_obj_t *args) {
|
||||
rt_uint16_t x = mp_obj_get_int(args[1]);
|
||||
rt_uint16_t y = mp_obj_get_int(args[2]);
|
||||
rt_uint16_t length = mp_obj_get_int(args[3]);
|
||||
rt_uint16_t wide = mp_obj_get_int(args[4]);
|
||||
|
||||
mp_buffer_info_t bufinfo;
|
||||
if (mp_get_buffer(args[5], &bufinfo, MP_BUFFER_READ))
|
||||
{
|
||||
lcd_show_image( x, y, length, wide, (const rt_uint8_t *)bufinfo.buf);
|
||||
}
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_lcd_show_image_obj, 6, 6, machine_lcd_show_image);
|
||||
|
||||
STATIC rt_uint16_t rgb888to565(rt_uint32_t RGB)
|
||||
{
|
||||
int R, G, B;
|
||||
R = (RGB >> 19) & 0x1F;
|
||||
G = (RGB >> 10) & 0x3F;
|
||||
B = (RGB >> 3) & 0x1F;
|
||||
return (R << 11) | (G << 5) | B;
|
||||
}
|
||||
|
||||
/// \method show_image array
|
||||
///
|
||||
/// display the image on the lcd.
|
||||
/// @param x x position
|
||||
/// @param y y position
|
||||
/// @param file bmp file pathname
|
||||
STATIC mp_obj_t machine_lcd_show_bmp(size_t n_args, const mp_obj_t *args) {
|
||||
#define BMP_INFO_SIZE 54
|
||||
rt_uint16_t x = mp_obj_get_int(args[1]);
|
||||
rt_uint16_t y = mp_obj_get_int(args[2]);
|
||||
const char *pathname = mp_obj_str_get_str(args[3]);
|
||||
|
||||
int fd, len;
|
||||
fd = open(pathname, O_RDONLY, 0);
|
||||
if (fd < 0)
|
||||
{
|
||||
mp_raise_OSError(MP_EINVAL);
|
||||
}
|
||||
|
||||
void *bmp_info = rt_malloc(BMP_INFO_SIZE);
|
||||
if (bmp_info == RT_NULL)
|
||||
{
|
||||
mp_raise_OSError(MP_ENOMEM);
|
||||
}
|
||||
|
||||
len = read(fd, bmp_info, BMP_INFO_SIZE);
|
||||
if (len < 0)
|
||||
{
|
||||
close(fd);
|
||||
mp_raise_OSError(MP_EINVAL);
|
||||
}
|
||||
|
||||
rt_uint32_t width = *(rt_uint32_t *)(bmp_info + 18);
|
||||
rt_uint32_t heigth = *(rt_uint32_t *)(bmp_info + 22);
|
||||
rt_uint16_t bit_count = *(rt_uint16_t *)(bmp_info + 28);
|
||||
|
||||
if (bit_count != 32)
|
||||
{
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError,
|
||||
"bit count : %d, only support 32-bit bmp picture", bit_count));
|
||||
}
|
||||
|
||||
void *image_buf = rt_malloc(2 * width);
|
||||
if (image_buf == RT_NULL)
|
||||
{
|
||||
mp_raise_OSError(MP_ENOMEM);
|
||||
}
|
||||
|
||||
void *row_buf = rt_malloc(4 * width);
|
||||
if (row_buf == RT_NULL)
|
||||
{
|
||||
mp_raise_OSError(MP_ENOMEM);
|
||||
}
|
||||
|
||||
int image_index, row_index;
|
||||
rt_uint16_t rgb565_temp;
|
||||
|
||||
for(int i = 0; i < heigth; i++)
|
||||
{
|
||||
image_index = 0;
|
||||
row_index = 0;
|
||||
|
||||
len = read(fd, row_buf, 4 * width);
|
||||
if (len < 0)
|
||||
{
|
||||
close(fd);
|
||||
mp_raise_OSError(MP_EINVAL);
|
||||
}
|
||||
|
||||
while(row_index < (4 * width))
|
||||
{
|
||||
rgb565_temp = rgb888to565(*(rt_uint32_t *)(row_buf + row_index));
|
||||
*(rt_uint8_t *)(image_buf + image_index) = (rgb565_temp >> 8);
|
||||
*(rt_uint8_t *)(image_buf + image_index + 1) = rgb565_temp & 0xff;
|
||||
|
||||
row_index += 4;
|
||||
image_index += 2;
|
||||
}
|
||||
|
||||
lcd_show_image( x, y--, width, 1, (const rt_uint8_t *)image_buf);
|
||||
}
|
||||
|
||||
close(fd);
|
||||
rt_free(bmp_info);
|
||||
rt_free(image_buf);
|
||||
rt_free(row_buf);
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_lcd_show_bmp_obj, 4, 4, machine_lcd_show_bmp);
|
||||
|
||||
STATIC const mp_rom_map_elem_t machine_lcd_locals_dict_table[] = {
|
||||
// instance methods
|
||||
{ MP_ROM_QSTR(MP_QSTR_light), MP_ROM_PTR(&machine_lcd_light_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_fill), MP_ROM_PTR(&machine_lcd_fill_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_pixel), MP_ROM_PTR(&machine_lcd_pixel_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_text), MP_ROM_PTR(&machine_lcd_text_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_line), MP_ROM_PTR(&machine_lcd_line_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_rectangle), MP_ROM_PTR(&machine_lcd_rectangle_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_circle), MP_ROM_PTR(&machine_lcd_circle_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_set_color), MP_ROM_PTR(&machine_lcd_set_color_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_show_image), MP_ROM_PTR(&machine_lcd_show_image_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_show_bmp), MP_ROM_PTR(&machine_lcd_show_bmp_obj) },
|
||||
// color
|
||||
{ MP_ROM_QSTR(MP_QSTR_WHITE), MP_ROM_INT(WHITE) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_BLACK), MP_ROM_INT(BLACK) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_BLUE), MP_ROM_INT(BLUE) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_BRED), MP_ROM_INT(BRED) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_GRED), MP_ROM_INT(GRED) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_GBLUE), MP_ROM_INT(GBLUE) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_RED), MP_ROM_INT(RED) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_MAGENTA), MP_ROM_INT(MAGENTA) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_GREEN), MP_ROM_INT(GREEN) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_CYAN), MP_ROM_INT(CYAN) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_YELLOW), MP_ROM_INT(YELLOW) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_BROWN), MP_ROM_INT(BROWN) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_BRRED), MP_ROM_INT(BRRED) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_GRAY), MP_ROM_INT(GRAY) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_GRAY175), MP_ROM_INT(GRAY175) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_GRAY151), MP_ROM_INT(GRAY151) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_GRAY187), MP_ROM_INT(GRAY187) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_GRAY240), MP_ROM_INT(GRAY240) },
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(machine_lcd_locals_dict, machine_lcd_locals_dict_table);
|
||||
|
||||
const mp_obj_type_t machine_lcd_type = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_LCD,
|
||||
.make_new = machine_lcd_make_new,
|
||||
.locals_dict = (mp_obj_dict_t*)&machine_lcd_locals_dict,
|
||||
};
|
||||
|
||||
#endif // MICROPY_PY_MACHINE_LCD
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2019 SummerGift <SummerGift@qq.com>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef MICROPY_INCLUDED_MACHINE_LCD_H
|
||||
#define MICROPY_INCLUDED_MACHINE_LCD_H
|
||||
|
||||
extern const mp_obj_type_t machine_lcd_type;
|
||||
|
||||
#endif // MICROPY_INCLUDED_MACHINE_LCD_H
|
||||
@@ -0,0 +1,298 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Armink (armink.ztl@gmail.com)
|
||||
*
|
||||
* 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 <stdint.h>
|
||||
#include <string.h>
|
||||
#include <rtthread.h>
|
||||
#include <drivers/pin.h>
|
||||
#include "py/runtime.h"
|
||||
#include "py/gc.h"
|
||||
#include "py/mphal.h"
|
||||
#include "py/mperrno.h"
|
||||
#include "py/stream.h"
|
||||
#include "modmachine.h"
|
||||
|
||||
#if MICROPY_PY_PIN
|
||||
|
||||
#define GPIO_MODE_IN ((uint32_t)0x00000000) /*!< Input Floating Mode */
|
||||
#define GPIO_MODE_OUT_PP ((uint32_t)0x00000001) /*!< Output Push Pull Mode */
|
||||
#define GPIO_MODE_OUT_OD ((uint32_t)0x00000011) /*!< Output Open Drain Mode */
|
||||
#define GPIO_MODE_AF_PP ((uint32_t)0x00000002) /*!< Alternate Function Push Pull Mode */
|
||||
#define GPIO_MODE_AF_OD ((uint32_t)0x00000012) /*!< Alternate Function Open Drain Mode */
|
||||
#define GPIO_MODE_ANALOG ((uint32_t)0x00000003) /*!< Analog Mode */
|
||||
#define GPIO_NOPULL ((uint32_t)0x00000000) /*!< No Pull-up or Pull-down activation */
|
||||
#define GPIO_PULLUP ((uint32_t)0x00000001) /*!< Pull-up activation */
|
||||
#define GPIO_PULLDOWN ((uint32_t)0x00000002) /*!< Pull-down activation */
|
||||
#define GPIO_MODE_IT_RISING ((uint32_t)0x10110000) /*!< External Interrupt Mode with Rising edge trigger detection */
|
||||
#define GPIO_MODE_IT_FALLING ((uint32_t)0x10210000) /*!< External Interrupt Mode with Falling edge trigger detection */
|
||||
#define GPIO_MODE_IT_RISING_FALLING ((uint32_t)0x10310000) /*!< External Interrupt Mode with Rising/Falling edge trigger detection */
|
||||
|
||||
const mp_obj_base_t machine_pin_obj_template = {&machine_pin_type};
|
||||
|
||||
void mp_pin_od_write(void *machine_pin, int stat) {
|
||||
if (stat == PIN_LOW) {
|
||||
rt_pin_mode(((machine_pin_obj_t *)machine_pin)->pin, PIN_MODE_OUTPUT);
|
||||
rt_pin_write(((machine_pin_obj_t *)machine_pin)->pin, stat);
|
||||
} else {
|
||||
rt_pin_mode(((machine_pin_obj_t *)machine_pin)->pin, PIN_MODE_INPUT_PULLUP);
|
||||
}
|
||||
}
|
||||
|
||||
void mp_hal_pin_open_set(void *machine_pin, int mode) {
|
||||
rt_pin_mode(((machine_pin_obj_t *)machine_pin)->pin, mode);
|
||||
}
|
||||
|
||||
char* mp_hal_pin_get_name(void *machine_pin) {
|
||||
return ((machine_pin_obj_t *)machine_pin)->name;
|
||||
}
|
||||
|
||||
STATIC mp_obj_t machine_pin_obj_init_helper(machine_pin_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args);
|
||||
|
||||
STATIC void machine_pin_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
|
||||
machine_pin_obj_t *self = self_in;
|
||||
mp_printf(print, "<Pin %d>", self->pin);
|
||||
}
|
||||
|
||||
// constructor(drv_name, pin, ...)
|
||||
mp_obj_t mp_pin_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
|
||||
mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true);
|
||||
|
||||
// get the wanted port
|
||||
if (!MP_OBJ_IS_TYPE(args[0], &mp_type_tuple)) {
|
||||
mp_raise_ValueError("Pin id must be tuple of (\"GPIO_x\", pin#)");
|
||||
}
|
||||
mp_obj_t *items;
|
||||
mp_obj_get_array_fixed_n(args[0], 2, &items);
|
||||
const char *pin_name = mp_obj_str_get_str(items[0]);
|
||||
int wanted_pin = mp_obj_get_int(items[1]);
|
||||
|
||||
machine_pin_obj_t *pin = m_new_obj(machine_pin_obj_t);
|
||||
if (!pin) {
|
||||
mp_raise_OSError(MP_ENOMEM);
|
||||
}
|
||||
|
||||
strncpy(pin->name, pin_name, sizeof(pin->name));
|
||||
pin->base = machine_pin_obj_template;
|
||||
pin->pin = wanted_pin;
|
||||
|
||||
if (n_args > 1 || n_kw > 0) {
|
||||
// pin mode given, so configure this GPIO
|
||||
mp_map_t kw_args;
|
||||
mp_map_init_fixed_table(&kw_args, n_kw, args + n_args);
|
||||
machine_pin_obj_init_helper(pin, n_args - 1, args + 1, &kw_args);
|
||||
}
|
||||
|
||||
return (mp_obj_t)pin;
|
||||
}
|
||||
|
||||
// pin.init(mode, pull=None, *, value)
|
||||
STATIC mp_obj_t machine_pin_obj_init_helper(machine_pin_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
enum { ARG_mode, ARG_pull, ARG_value };
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{ MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT },
|
||||
{ MP_QSTR_pull, MP_ARG_OBJ, {.u_obj = mp_const_none}},
|
||||
{ MP_QSTR_value, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL}},
|
||||
};
|
||||
|
||||
// parse args
|
||||
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);
|
||||
|
||||
// get io mode
|
||||
uint mode = args[ARG_mode].u_int;
|
||||
|
||||
// get pull mode
|
||||
uint pull = GPIO_NOPULL;
|
||||
|
||||
if (args[ARG_pull].u_obj != mp_const_none) {
|
||||
pull = mp_obj_get_int(args[ARG_pull].u_obj);
|
||||
}
|
||||
|
||||
switch(mode) {
|
||||
case GPIO_MODE_IN: {
|
||||
if (pull == GPIO_PULLUP) {
|
||||
mode = PIN_MODE_INPUT_PULLUP;
|
||||
} else if (pull == GPIO_PULLDOWN) {
|
||||
mode = PIN_MODE_INPUT_PULLDOWN;
|
||||
} else {
|
||||
mode = PIN_MODE_INPUT;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case GPIO_MODE_OUT_PP : {
|
||||
mode = PIN_MODE_OUTPUT;
|
||||
break;
|
||||
}
|
||||
case GPIO_MODE_OUT_OD : {
|
||||
mode = PIN_MODE_OUTPUT_OD;
|
||||
break;
|
||||
}
|
||||
case GPIO_MODE_AF_PP :
|
||||
case GPIO_MODE_AF_OD :
|
||||
case GPIO_MODE_ANALOG :
|
||||
//TODO
|
||||
mp_raise_NotImplementedError("not implemented pin mode");
|
||||
}
|
||||
|
||||
rt_pin_mode(self->pin, mode);
|
||||
|
||||
// get initial value
|
||||
if (args[ARG_value].u_obj != MP_OBJ_NULL) {
|
||||
rt_pin_write(self->pin, mp_obj_is_true(args[ARG_value].u_obj));
|
||||
}
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
// fast method for getting/setting pin value
|
||||
STATIC mp_obj_t machine_pin_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {
|
||||
mp_arg_check_num(n_args, n_kw, 0, 1, false);
|
||||
machine_pin_obj_t *self = self_in;
|
||||
if (n_args == 0) {
|
||||
return mp_obj_new_bool(rt_pin_read(self->pin));
|
||||
} else {
|
||||
rt_pin_write(self->pin, mp_obj_is_true(args[0]));
|
||||
return mp_const_none;
|
||||
}
|
||||
}
|
||||
|
||||
// pin.init(mode, pull)
|
||||
STATIC mp_obj_t machine_pin_obj_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
|
||||
return machine_pin_obj_init_helper(args[0], n_args - 1, args + 1, kw_args);
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_KW(machine_pin_init_obj, 1, machine_pin_obj_init);
|
||||
|
||||
// pin.value([value])
|
||||
STATIC mp_obj_t machine_pin_value(size_t n_args, const mp_obj_t *args) {
|
||||
return machine_pin_call(args[0], n_args - 1, 0, args + 1);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_pin_value_obj, 1, 2, machine_pin_value);
|
||||
|
||||
// pin.name()
|
||||
STATIC mp_obj_t machine_pin_name(size_t n_args, const mp_obj_t *args) {
|
||||
machine_pin_obj_t *self = (machine_pin_obj_t *)args[0];
|
||||
return mp_obj_new_str(self->name, strlen(self->name));
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_pin_name_obj, 1, 2, machine_pin_name);
|
||||
|
||||
// pin.pin()
|
||||
STATIC mp_obj_t machine_pin_pin(size_t n_args, const mp_obj_t *args) {
|
||||
return MP_OBJ_NEW_SMALL_INT(((machine_pin_obj_t *)args[0])->pin);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_pin_pin_obj, 1, 2, machine_pin_pin);
|
||||
|
||||
STATIC mp_uint_t machine_pin_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int *errcode) {
|
||||
(void)errcode;
|
||||
machine_pin_obj_t *self = self_in;
|
||||
|
||||
switch (request) {
|
||||
case MP_PIN_READ: {
|
||||
uint32_t pin_val = rt_pin_read(self->pin);
|
||||
return pin_val;
|
||||
}
|
||||
case MP_PIN_WRITE: {
|
||||
rt_pin_write(self->pin, arg);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
*errcode = MP_EINVAL;
|
||||
return MP_STREAM_ERROR;
|
||||
}
|
||||
|
||||
STATIC void machine_pin_isr_handler(void *arg) {
|
||||
machine_pin_obj_t *self = arg;
|
||||
mp_sched_schedule(self->pin_isr_cb, MP_OBJ_FROM_PTR(self));
|
||||
}
|
||||
|
||||
// pin.irq(handler=None, trigger=IRQ_FALLING|IRQ_RISING)
|
||||
STATIC mp_obj_t machine_pin_irq(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
enum { ARG_handler, ARG_trigger, ARG_wake };
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{ MP_QSTR_handler, MP_ARG_OBJ, {.u_obj = mp_const_none} },
|
||||
{ MP_QSTR_trigger, MP_ARG_INT, {.u_int = PIN_IRQ_MODE_RISING} },
|
||||
};
|
||||
machine_pin_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
|
||||
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
|
||||
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
|
||||
|
||||
if (n_args > 1 || kw_args->used != 0) {
|
||||
// configure irq
|
||||
self->pin_isr_cb = args[ARG_handler].u_obj;
|
||||
uint32_t trigger = args[ARG_trigger].u_int;
|
||||
|
||||
rt_pin_mode(self->pin, PIN_MODE_INPUT_PULLUP);
|
||||
rt_pin_attach_irq(self->pin, trigger, machine_pin_isr_handler, (void*)self);
|
||||
rt_pin_irq_enable(self->pin, PIN_IRQ_ENABLE);
|
||||
}
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_pin_irq_obj, 1, machine_pin_irq);
|
||||
|
||||
STATIC const mp_rom_map_elem_t machine_pin_locals_dict_table[] = {
|
||||
// instance methods
|
||||
{ MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_pin_init_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_value), MP_ROM_PTR(&machine_pin_value_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_name), MP_ROM_PTR(&machine_pin_name_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_pin), MP_ROM_PTR(&machine_pin_pin_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_irq), MP_ROM_PTR(&machine_pin_irq_obj) },
|
||||
|
||||
// class constants
|
||||
{ MP_ROM_QSTR(MP_QSTR_ALT_OD), MP_ROM_INT(GPIO_MODE_AF_OD) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_ALT_PP), MP_ROM_INT(GPIO_MODE_AF_PP) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_ANALOG), MP_ROM_INT(GPIO_MODE_ANALOG) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_IN), MP_ROM_INT(GPIO_MODE_IN) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_OUT_PP), MP_ROM_INT(GPIO_MODE_OUT_PP) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_OUT_OD), MP_ROM_INT(GPIO_MODE_OUT_OD) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_PULL_DOWN), MP_ROM_INT(GPIO_PULLDOWN) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_PULL_NONE), MP_ROM_INT(GPIO_NOPULL) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_PULL_UP), MP_ROM_INT(GPIO_PULLUP) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_IRQ_RISING), MP_ROM_INT(PIN_IRQ_MODE_RISING) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_IRQ_FALLING), MP_ROM_INT(PIN_IRQ_MODE_FALLING) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_IRQ_RISING_FALLING), MP_ROM_INT(PIN_IRQ_MODE_RISING_FALLING) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_IRQ_LOW_LEVEL), MP_ROM_INT(PIN_IRQ_MODE_LOW_LEVEL) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_IRQ_HIGH_LEVEL), MP_ROM_INT(PIN_IRQ_MODE_HIGH_LEVEL) },
|
||||
};
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(machine_pin_locals_dict, machine_pin_locals_dict_table);
|
||||
|
||||
STATIC const mp_pin_p_t machine_pin_pin_p = {
|
||||
.ioctl = machine_pin_ioctl,
|
||||
};
|
||||
|
||||
const mp_obj_type_t machine_pin_type = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_Pin,
|
||||
.print = machine_pin_print,
|
||||
.make_new = mp_pin_make_new,
|
||||
.call = machine_pin_call,
|
||||
.protocol = &machine_pin_pin_p,
|
||||
.locals_dict = (mp_obj_t)&machine_pin_locals_dict,
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,276 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2019 ChenYong (chenyong@rt-thread.com)
|
||||
*
|
||||
* 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 <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "py/nlr.h"
|
||||
#include "py/runtime.h"
|
||||
#include "modmachine.h"
|
||||
#include "mphalport.h"
|
||||
|
||||
#ifdef MICROPYTHON_USING_MACHINE_PWM
|
||||
|
||||
#include <rtthread.h>
|
||||
#include <drivers/rt_drv_pwm.h>
|
||||
|
||||
#define MP_PWM_PULSE_MAX 255
|
||||
#define MP_PWM_PERIOD_GET(freq) (1000000000 / (freq))
|
||||
#define MP_PWM_PULSE_GET(period, duty) ((period) / MP_PWM_PULSE_MAX * (duty))
|
||||
|
||||
extern const mp_obj_type_t machine_pwm_type;
|
||||
|
||||
typedef struct _machine_pwm_obj_t {
|
||||
mp_obj_base_t base;
|
||||
struct rt_device_pwm *pwm_device;
|
||||
char dev_name[RT_NAME_MAX];
|
||||
uint8_t is_init;
|
||||
int8_t id;
|
||||
uint8_t channel;
|
||||
uint8_t duty;
|
||||
uint32_t freq;
|
||||
} machine_pwm_obj_t;
|
||||
|
||||
STATIC void machine_pwm_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
|
||||
machine_pwm_obj_t *self = self_in;
|
||||
|
||||
mp_printf(print, "PWM(%p; ", self);
|
||||
if (self->id >= 0) {
|
||||
mp_printf(print, "pwm_id=%d, ", self->id);
|
||||
} else {
|
||||
mp_printf(print, "pwm_name=%s, ", self->dev_name);
|
||||
}
|
||||
mp_printf(print, "channel=%d, ", self->channel);
|
||||
mp_printf(print, "freq=%d, ", self->freq);
|
||||
mp_printf(print, "duty=%d)", self->duty);
|
||||
}
|
||||
|
||||
STATIC void error_check(bool status, const char *msg) {
|
||||
if (!status) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, msg));
|
||||
}
|
||||
}
|
||||
|
||||
STATIC void machine_pwm_init_helper(machine_pwm_obj_t *self,
|
||||
size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
rt_err_t result = RT_EOK;
|
||||
uint32_t period = 0, pulse = 0;
|
||||
char pwm_dev_name[RT_NAME_MAX];
|
||||
struct rt_device_pwm *pwm_device = RT_NULL;
|
||||
enum { ARG_channel, ARG_freq, ARG_duty };
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{ MP_QSTR_channel, MP_ARG_INT, {.u_int = 0} },
|
||||
{ MP_QSTR_freq, MP_ARG_INT, {.u_int = 1} },
|
||||
{ MP_QSTR_duty, MP_ARG_INT, {.u_int = 0} },
|
||||
};
|
||||
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);
|
||||
|
||||
int tval = args[ARG_channel].u_int;
|
||||
if ((tval < 0) || (tval > 4)) {
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError,
|
||||
"Bad channel %d", tval));
|
||||
}
|
||||
self->channel = tval;
|
||||
|
||||
tval = args[ARG_freq].u_int;
|
||||
if ((tval < 1) || (tval > 156250)) {
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError,
|
||||
"Bad frequency %d", tval));
|
||||
}
|
||||
self->freq = tval;
|
||||
|
||||
tval = args[ARG_duty].u_int;
|
||||
if ((tval < 0) || (tval > 255)) {
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError,
|
||||
"Bad duty %d", tval));
|
||||
}
|
||||
self->duty = tval;
|
||||
|
||||
if (self->id >= 0) {
|
||||
rt_snprintf(pwm_dev_name, sizeof(pwm_dev_name), "pwm%d", self->id);
|
||||
} else {
|
||||
rt_strncpy(pwm_dev_name, self->dev_name, RT_NAME_MAX);
|
||||
}
|
||||
|
||||
pwm_device = (struct rt_device_pwm *) rt_device_find(pwm_dev_name);
|
||||
if (pwm_device == RT_NULL || pwm_device->parent.type != RT_Device_Class_Miscellaneous) {
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError,
|
||||
"PWM(%s) don't exist", pwm_dev_name));
|
||||
}
|
||||
self->pwm_device = pwm_device;
|
||||
|
||||
// get period number by frequency
|
||||
period = MP_PWM_PERIOD_GET(self->freq);
|
||||
// get pulse number by duty
|
||||
pulse = MP_PWM_PULSE_GET(period, self->duty);
|
||||
|
||||
result = rt_pwm_set(pwm_device, self->channel, period, pulse);
|
||||
error_check(result == RT_EOK, "PWM set information error");
|
||||
|
||||
result = rt_pwm_enable(pwm_device, self->channel);
|
||||
error_check(result == RT_EOK, "PWM enable error");
|
||||
|
||||
self->is_init = RT_TRUE;
|
||||
}
|
||||
|
||||
STATIC mp_obj_t machine_pwm_make_new(const mp_obj_type_t *type,
|
||||
size_t n_args, size_t n_kw, const mp_obj_t *args) {
|
||||
mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true);
|
||||
|
||||
// create PWM object from the given pin
|
||||
machine_pwm_obj_t *self = m_new_obj(machine_pwm_obj_t);
|
||||
self->base.type = &machine_pwm_type;
|
||||
self->is_init = RT_FALSE;
|
||||
|
||||
// check input PWM device name or ID
|
||||
if (mp_obj_is_small_int(args[0])) {
|
||||
self->id = mp_obj_get_int(args[0]);
|
||||
} else if (mp_obj_is_qstr(args[0])) {
|
||||
self->id = -1;
|
||||
rt_strncpy(self->dev_name, mp_obj_str_get_str(args[0]), RT_NAME_MAX);
|
||||
} else {
|
||||
error_check(0, "Input PWM device name or ID error.");
|
||||
}
|
||||
|
||||
self->channel = 0;
|
||||
self->freq = 1;
|
||||
self->duty = 0;
|
||||
|
||||
mp_map_t kw_args;
|
||||
mp_map_init_fixed_table(&kw_args, n_kw, args + n_args);
|
||||
machine_pwm_init_helper(self, n_args - 1, args + 1, &kw_args);
|
||||
|
||||
return MP_OBJ_FROM_PTR(self);
|
||||
}
|
||||
|
||||
STATIC mp_obj_t machine_pwm_init(size_t n_args,
|
||||
const mp_obj_t *args, mp_map_t *kw_args) {
|
||||
machine_pwm_init_helper(args[0], n_args - 1, args + 1, kw_args);
|
||||
return mp_const_none;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_KW(machine_pwm_init_obj, 1, machine_pwm_init);
|
||||
|
||||
STATIC mp_obj_t machine_pwm_deinit(mp_obj_t self_in) {
|
||||
machine_pwm_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
rt_err_t result = RT_EOK;
|
||||
|
||||
if (self->is_init == RT_TRUE) {
|
||||
result = rt_pwm_disable(self->pwm_device, self->channel);
|
||||
error_check(result == RT_EOK, "PWM disable error");
|
||||
self->is_init = RT_FALSE;
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_pwm_deinit_obj, machine_pwm_deinit);
|
||||
|
||||
STATIC mp_obj_t machine_pwm_freq(size_t n_args, const mp_obj_t *args) {
|
||||
machine_pwm_obj_t *self = MP_OBJ_TO_PTR(args[0]);
|
||||
uint32_t period = 0, pulse = 0;
|
||||
rt_err_t result = RT_EOK;
|
||||
|
||||
error_check(self->is_init == RT_TRUE, "PWM device uninitialized");
|
||||
|
||||
if (n_args == 1) {
|
||||
// get
|
||||
return MP_OBJ_NEW_SMALL_INT(self->freq);
|
||||
}
|
||||
|
||||
// set
|
||||
int tval = mp_obj_get_int(args[1]);
|
||||
if ((tval < 1) || (tval > 156250)) {
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError,
|
||||
"Bad frequency %d", tval));
|
||||
}
|
||||
|
||||
// get period number by frequency
|
||||
period = MP_PWM_PERIOD_GET(tval);
|
||||
// get pulse number by duty
|
||||
pulse = MP_PWM_PULSE_GET(period, self->duty);
|
||||
|
||||
result = rt_pwm_set(self->pwm_device, self->channel, period, pulse);
|
||||
error_check(result == RT_EOK, "PWM set information error");
|
||||
self->freq = tval;
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_pwm_freq_obj, 1, 2, machine_pwm_freq);
|
||||
|
||||
STATIC mp_obj_t machine_pwm_duty(size_t n_args, const mp_obj_t *args) {
|
||||
machine_pwm_obj_t *self = MP_OBJ_TO_PTR(args[0]);
|
||||
uint32_t period = 0, pulse = 0;
|
||||
rt_err_t result = RT_EOK;
|
||||
|
||||
error_check(self->is_init == RT_TRUE, "PWM device uninitialized");
|
||||
|
||||
if (n_args == 1) {
|
||||
// get
|
||||
return MP_OBJ_NEW_SMALL_INT(self->duty);
|
||||
}
|
||||
|
||||
// set
|
||||
int tval = mp_obj_get_int(args[1]);
|
||||
if ((tval < 0) || (tval > 255)) {
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError,
|
||||
"Bad duty %d", tval));
|
||||
}
|
||||
|
||||
// get period number by frequency
|
||||
period = MP_PWM_PERIOD_GET(self->freq);
|
||||
// get pulse number by duty
|
||||
pulse = MP_PWM_PULSE_GET(period, tval);
|
||||
|
||||
result = rt_pwm_set(self->pwm_device, self->channel, period, pulse);
|
||||
error_check(result == RT_EOK, "PWM set information error");
|
||||
self->duty = tval;
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_pwm_duty_obj,
|
||||
1, 2, machine_pwm_duty);
|
||||
|
||||
STATIC const mp_rom_map_elem_t machine_pwm_locals_dict_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_pwm_init_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_pwm_deinit_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_freq), MP_ROM_PTR(&machine_pwm_freq_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_duty), MP_ROM_PTR(&machine_pwm_duty_obj) },
|
||||
};
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(machine_pwm_locals_dict,
|
||||
machine_pwm_locals_dict_table);
|
||||
|
||||
const mp_obj_type_t machine_pwm_type = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_PWM,
|
||||
.print = machine_pwm_print,
|
||||
.make_new = machine_pwm_make_new,
|
||||
.locals_dict = (mp_obj_dict_t *) &machine_pwm_locals_dict,
|
||||
};
|
||||
|
||||
#endif // MICROPYTHON_USING_MACHINE_PWM
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2019 ChenYong (chenyong@rt-thread.com)
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef MICROPY_INCLUDED_MACHINE_PWM_H
|
||||
#define MICROPY_INCLUDED_MACHINE_PWM_H
|
||||
|
||||
#include "py/obj.h"
|
||||
#include <rtthread.h>
|
||||
|
||||
extern const mp_obj_type_t machine_pwm_type;
|
||||
|
||||
#endif // MICROPY_INCLUDED_MACHINE_PWM_H
|
||||
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2019 ChenYong (chenyong@rt-thread.com)
|
||||
*
|
||||
* 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 <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "py/nlr.h"
|
||||
#include "py/obj.h"
|
||||
#include "py/runtime.h"
|
||||
#include "py/mphal.h"
|
||||
#include "lib/timeutils/timeutils.h"
|
||||
#include "modmachine.h"
|
||||
|
||||
#ifdef MICROPYTHON_USING_MACHINE_RTC
|
||||
|
||||
#include <rtthread.h>
|
||||
#include <drivers/rtc.h>
|
||||
#include <time.h>
|
||||
|
||||
#define MP_YEAR_BASE 1900
|
||||
|
||||
const mp_obj_type_t machine_rtc_type;
|
||||
|
||||
// singleton RTC object
|
||||
STATIC const mp_obj_base_t machine_rtc_obj = {&machine_rtc_type};
|
||||
|
||||
STATIC void error_check(bool status, const char *msg) {
|
||||
if (!status) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, msg));
|
||||
}
|
||||
}
|
||||
|
||||
STATIC mp_obj_t machine_rtc_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
|
||||
#define MP_RTC_DEV_NAME "rtc"
|
||||
rt_device_t rtc_deivce = RT_NULL;
|
||||
|
||||
// check arguments
|
||||
mp_arg_check_num(n_args, n_kw, 0, 0, false);
|
||||
|
||||
// check RTC device
|
||||
rtc_deivce = rt_device_find(MP_RTC_DEV_NAME);
|
||||
if (rtc_deivce == RT_NULL || rtc_deivce->type != RT_Device_Class_RTC) {
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "RTC(%s) don't exist", MP_RTC_DEV_NAME));
|
||||
}
|
||||
|
||||
// return constant object
|
||||
return (mp_obj_t)&machine_rtc_obj;
|
||||
}
|
||||
|
||||
STATIC mp_obj_t machine_rtc_datetime_helper(mp_uint_t n_args, const mp_obj_t *args) {
|
||||
if (n_args == 1) {
|
||||
struct tm *tblock;
|
||||
time_t t;
|
||||
// Get time
|
||||
t = time(RT_NULL);
|
||||
tblock = localtime(&t);
|
||||
|
||||
mp_uint_t seconds = timeutils_mktime(tblock->tm_year + MP_YEAR_BASE, tblock->tm_mon + 1, tblock->tm_mday,
|
||||
tblock->tm_hour, tblock->tm_min, tblock->tm_sec);
|
||||
timeutils_struct_time_t tm;
|
||||
timeutils_seconds_since_2000_to_struct_time(seconds, &tm);
|
||||
|
||||
mp_obj_t tuple[8] = {
|
||||
mp_obj_new_int(tm.tm_year),
|
||||
mp_obj_new_int(tm.tm_mon),
|
||||
mp_obj_new_int(tm.tm_mday),
|
||||
mp_obj_new_int(tm.tm_wday),
|
||||
mp_obj_new_int(tm.tm_hour),
|
||||
mp_obj_new_int(tm.tm_min),
|
||||
mp_obj_new_int(tm.tm_sec),
|
||||
mp_obj_new_int(0)
|
||||
};
|
||||
|
||||
return mp_obj_new_tuple(8, tuple);
|
||||
} else {
|
||||
// Set time
|
||||
rt_err_t result;
|
||||
mp_obj_t *items;
|
||||
|
||||
mp_obj_get_array_fixed_n(args[1], 8, &items);
|
||||
result = set_date(mp_obj_get_int(items[0]), mp_obj_get_int(items[1]), mp_obj_get_int(items[2]));
|
||||
error_check(result == RT_EOK, "Set date error");
|
||||
result = set_time(mp_obj_get_int(items[4]), mp_obj_get_int(items[5]), mp_obj_get_int(items[6]));
|
||||
error_check(result == RT_EOK, "Set time error");
|
||||
return mp_const_none;
|
||||
}
|
||||
}
|
||||
|
||||
STATIC mp_obj_t machine_rtc_now(mp_uint_t n_args, const mp_obj_t *args) {
|
||||
return machine_rtc_datetime_helper(1, args);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_rtc_now_obj, 0, 1, machine_rtc_now);
|
||||
|
||||
STATIC mp_obj_t machine_rtc_init(mp_uint_t n_args, const mp_obj_t *args) {
|
||||
return machine_rtc_datetime_helper(n_args, args);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_rtc_init_obj, 1, 2, machine_rtc_init);
|
||||
|
||||
STATIC mp_obj_t machine_rtc_deinit(mp_uint_t n_args, const mp_obj_t *args) {
|
||||
rt_err_t result;
|
||||
struct tm tblock;
|
||||
|
||||
tblock.tm_year = 2015 - MP_YEAR_BASE;
|
||||
tblock.tm_mon = 0;
|
||||
tblock.tm_mday = 1;
|
||||
tblock.tm_hour = 0;
|
||||
tblock.tm_min = 0;
|
||||
tblock.tm_sec = 0;
|
||||
result = set_date(tblock.tm_year + MP_YEAR_BASE, tblock.tm_mon + 1, tblock.tm_mday);
|
||||
error_check(result == RT_EOK, "Set date error");
|
||||
result = set_time(tblock.tm_hour, tblock.tm_min, tblock.tm_sec);
|
||||
error_check(result == RT_EOK, "Set time error");
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_rtc_deinit_obj, 0, 1, machine_rtc_deinit);
|
||||
|
||||
STATIC const mp_rom_map_elem_t machine_rtc_locals_dict_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_rtc_init_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_rtc_deinit_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_now), MP_ROM_PTR(&machine_rtc_now_obj) },
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(machine_rtc_locals_dict, machine_rtc_locals_dict_table);
|
||||
|
||||
const mp_obj_type_t machine_rtc_type = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_RTC,
|
||||
.make_new = machine_rtc_make_new,
|
||||
.locals_dict = (mp_obj_t) &machine_rtc_locals_dict,
|
||||
};
|
||||
|
||||
#endif // MICROPYTHON_USING_MACHINE_RTC
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2019 ChenYong (chenyong@rt-thread.com)
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef MICROPY_INCLUDED_MACHINE_RTC_H
|
||||
#define MICROPY_INCLUDED_MACHINE_RTC_H
|
||||
|
||||
#include "py/obj.h"
|
||||
#include <rtthread.h>
|
||||
|
||||
extern const mp_obj_type_t machine_rtc_type;
|
||||
|
||||
#endif // MICROPY_INCLUDED_MACHINE_RTC_H
|
||||
@@ -0,0 +1,270 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2019 ChenYong (chenyong@rt-thread.com)
|
||||
*
|
||||
* 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 <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "py/obj.h"
|
||||
#include "py/runtime.h"
|
||||
#include "modmachine.h"
|
||||
#include "mphalport.h"
|
||||
|
||||
#ifdef MICROPYTHON_USING_MACHINE_TIMER
|
||||
|
||||
#include <rtthread.h>
|
||||
#include <drivers/hwtimer.h>
|
||||
#include "machine_timer.h"
|
||||
|
||||
#define MAX_TIMER 17
|
||||
|
||||
typedef struct _machine_timer_obj_t {
|
||||
mp_obj_base_t base;
|
||||
rt_device_t timer_device;
|
||||
char dev_name[RT_NAME_MAX];
|
||||
mp_obj_t timeout_cb;
|
||||
int8_t timerid;
|
||||
uint32_t timeout;
|
||||
rt_bool_t is_repeat;
|
||||
rt_bool_t is_init;
|
||||
} machine_timer_obj_t;
|
||||
|
||||
const mp_obj_type_t machine_timer_type;
|
||||
|
||||
STATIC void error_check(bool status, const char *msg) {
|
||||
if (!status) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, msg));
|
||||
}
|
||||
}
|
||||
|
||||
STATIC void machine_timer_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
|
||||
machine_timer_obj_t *self = self_in;
|
||||
|
||||
mp_printf(print, "Timer(%p; ", self);
|
||||
|
||||
if (self->timerid >= 0) {
|
||||
mp_printf(print, "timer_id=%d, ", self->timerid);
|
||||
} else {
|
||||
mp_printf(print, "timer_name=%s, ", self->dev_name);
|
||||
}
|
||||
mp_printf(print, "period=%d, ", self->timeout);
|
||||
mp_printf(print, "auto_reload=%d)", self->is_repeat);
|
||||
}
|
||||
|
||||
STATIC mp_obj_t machine_timer_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
|
||||
machine_timer_obj_t *self = m_new_obj(machine_timer_obj_t);
|
||||
char timer_dev_name[RT_NAME_MAX] = {0};
|
||||
|
||||
// check arguments
|
||||
mp_arg_check_num(n_args, n_kw, 1, 1, true);
|
||||
|
||||
// check input timer device name or ID
|
||||
if (mp_obj_is_small_int(args[0])) {
|
||||
int device_id = mp_obj_get_int(args[0]);
|
||||
self->timerid = device_id;
|
||||
self->timer_device->device_id = device_id;
|
||||
rt_snprintf(timer_dev_name, sizeof(timer_dev_name), "timer%d", mp_obj_get_int(args[0]));
|
||||
} else if (mp_obj_is_qstr(args[0])) {
|
||||
static int device_id = 0;
|
||||
self->timerid = -1;
|
||||
self->timer_device->device_id = device_id++;
|
||||
rt_strncpy(self->dev_name, mp_obj_str_get_str(args[0]), RT_NAME_MAX);
|
||||
rt_strncpy(timer_dev_name, self->dev_name, RT_NAME_MAX);
|
||||
} else {
|
||||
error_check(0, "Input ADC device name or ID error.");
|
||||
}
|
||||
|
||||
// find timer device
|
||||
self->timer_device = rt_device_find(timer_dev_name);
|
||||
if (self->timer_device == RT_NULL || self->timer_device->type != RT_Device_Class_Timer) {
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "Timer(%s) don't exist", timer_dev_name));
|
||||
}
|
||||
|
||||
// initialize timer device
|
||||
self->base.type = &machine_timer_type;
|
||||
self->timeout = 0;
|
||||
self->timeout_cb = RT_NULL;
|
||||
self->is_repeat = RT_TRUE;
|
||||
self->is_init = RT_FALSE;
|
||||
|
||||
// return constant object
|
||||
return MP_OBJ_FROM_PTR(self);
|
||||
}
|
||||
|
||||
static machine_timer_obj_t *timer_self[MAX_TIMER] = {RT_NULL};
|
||||
|
||||
STATIC mp_obj_t machine_timer_deinit(mp_obj_t self_in) {
|
||||
machine_timer_obj_t *self = self_in;
|
||||
rt_err_t result = RT_EOK;
|
||||
|
||||
if (self->is_init == RT_TRUE) {
|
||||
result = rt_device_close(self->timer_device);
|
||||
error_check(result == RT_EOK, "Timer device close error");
|
||||
self->is_init = RT_FALSE;
|
||||
timer_self[self->timer_device->device_id] = RT_NULL;
|
||||
}
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_timer_deinit_obj, machine_timer_deinit);
|
||||
|
||||
STATIC rt_err_t timer_event_handler(rt_device_t dev, rt_size_t size) {
|
||||
machine_timer_obj_t *self = timer_self[dev->device_id];
|
||||
|
||||
mp_sched_schedule(self->timeout_cb, MP_OBJ_FROM_PTR(self));
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
STATIC mp_obj_t machine_timer_init(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
|
||||
machine_timer_obj_t *self = (machine_timer_obj_t *)args[0];
|
||||
rt_bool_t result = RT_EOK;
|
||||
int mode = 0;
|
||||
|
||||
enum {
|
||||
ARG_mode,
|
||||
ARG_period,
|
||||
ARG_callback,
|
||||
};
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{ MP_QSTR_mode, MP_ARG_INT, {.u_int = 1} },
|
||||
{ MP_QSTR_period, MP_ARG_INT, {.u_int = 0xffffffff} },
|
||||
{ MP_QSTR_callback, MP_ARG_OBJ, {.u_obj = mp_const_none} },
|
||||
};
|
||||
|
||||
mp_arg_val_t dargs[MP_ARRAY_SIZE(allowed_args)];
|
||||
mp_arg_parse_all(n_args - 1, args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, dargs);
|
||||
|
||||
if (2 == n_args) {
|
||||
self->timeout = dargs[0].u_int;
|
||||
} else if (3 == n_args) {
|
||||
self->is_repeat = dargs[ARG_mode].u_int;
|
||||
self->timeout = dargs[ARG_period].u_int;
|
||||
} else if (4 == n_args) {
|
||||
self->is_repeat = dargs[ARG_mode].u_int;
|
||||
self->timeout = dargs[ARG_period].u_int;
|
||||
self->timeout_cb = dargs[ARG_callback].u_obj;
|
||||
} else {
|
||||
mp_raise_ValueError("invalid format");
|
||||
}
|
||||
|
||||
error_check(self->timeout > 0, "Set timeout value error");
|
||||
|
||||
if (self->is_init == RT_FALSE)
|
||||
{
|
||||
// open timer device
|
||||
result = rt_device_open(self->timer_device, RT_DEVICE_OFLAG_RDWR);
|
||||
error_check(result == RT_EOK, "Timer device open error");
|
||||
}
|
||||
|
||||
if (self->timeout_cb != RT_NULL) {
|
||||
// set callback timer
|
||||
if (timer_self[self->timer_device->device_id] && timer_self[self->timer_device->device_id] != self) {
|
||||
error_check(result == RT_EOK, "Timer device callback function already exists");
|
||||
} else {
|
||||
timer_self[self->timer_device->device_id] = self;
|
||||
}
|
||||
result = rt_device_set_rx_indicate(self->timer_device, timer_event_handler);
|
||||
error_check(result == RT_EOK, "Timer set timout callback error");
|
||||
}
|
||||
|
||||
// set timer mode
|
||||
mode = self->is_repeat ? HWTIMER_MODE_PERIOD : HWTIMER_MODE_ONESHOT;
|
||||
result = rt_device_control(self->timer_device, HWTIMER_CTRL_MODE_SET, &mode);
|
||||
error_check(result == RT_EOK, "Timer set mode error");
|
||||
|
||||
if (self->timeout) {
|
||||
rt_hwtimerval_t timeout_s;
|
||||
rt_size_t len;
|
||||
|
||||
timeout_s.sec = self->timeout / 1000; // second
|
||||
timeout_s.usec = self->timeout % 1000; // microsecond
|
||||
|
||||
len = rt_device_write(self->timer_device, 0, &timeout_s, sizeof(timeout_s));
|
||||
error_check(len == sizeof(timeout_s), "Timer set timout error");
|
||||
}
|
||||
|
||||
self->is_init = RT_TRUE;
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_timer_init_obj, 1, machine_timer_init);
|
||||
|
||||
|
||||
STATIC mp_obj_t machine_timer_callback(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
|
||||
machine_timer_obj_t *self = (machine_timer_obj_t *)args[0];
|
||||
rt_bool_t result = RT_EOK;
|
||||
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{ MP_QSTR_callback, MP_ARG_OBJ, {.u_obj = mp_const_none} },
|
||||
};
|
||||
|
||||
mp_arg_val_t dargs[MP_ARRAY_SIZE(allowed_args)];
|
||||
mp_arg_parse_all(n_args - 1, args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, dargs);
|
||||
|
||||
self->timeout_cb = dargs[0].u_obj;
|
||||
|
||||
if(n_args == 1)
|
||||
{
|
||||
self->timeout_cb = RT_NULL;
|
||||
self->timer_device->rx_indicate = RT_NULL;//Log-off callback function
|
||||
}
|
||||
else if(n_args == 2)
|
||||
{
|
||||
if(self->timeout_cb != mp_const_none)
|
||||
{
|
||||
timer_self[self->timer_device->device_id] = self;
|
||||
result = rt_device_set_rx_indicate(self->timer_device, timer_event_handler); //set callback timer
|
||||
error_check(result == RT_EOK, "Timer set timout callback error");
|
||||
}
|
||||
else
|
||||
{
|
||||
self->timeout_cb = RT_NULL;
|
||||
self->timer_device->rx_indicate = RT_NULL;//Log-off callback function
|
||||
}
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_timer_callback_obj, 0,machine_timer_callback);
|
||||
|
||||
STATIC const mp_rom_map_elem_t machine_timer_locals_dict_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_timer_deinit_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_timer_init_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_callback), MP_ROM_PTR(&machine_timer_callback_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_ONE_SHOT), MP_ROM_INT(RT_FALSE) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_PERIODIC), MP_ROM_INT(RT_TRUE) },
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(machine_timer_locals_dict, machine_timer_locals_dict_table);
|
||||
|
||||
const mp_obj_type_t machine_timer_type = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_Timer,
|
||||
.print = machine_timer_print,
|
||||
.make_new = machine_timer_make_new,
|
||||
.locals_dict = (mp_obj_t) &machine_timer_locals_dict,
|
||||
};
|
||||
|
||||
#endif // MICROPYTHON_USING_MACHINE_TIMER
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2019 ChenYong (chenyong@rt-thread.com)
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef MICROPY_INCLUDED_MACHINE_TIMER_H
|
||||
#define MICROPY_INCLUDED_MACHINE_TIMER_H
|
||||
|
||||
#include "py/obj.h"
|
||||
#include <rtthread.h>
|
||||
|
||||
extern const mp_obj_type_t machine_timer_type;
|
||||
|
||||
#endif // MICROPY_INCLUDED_MACHINE_TIMER_H
|
||||
|
||||
@@ -0,0 +1,274 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018 SummerGift <zhangyuan@rt-thread.com>
|
||||
*
|
||||
* 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/mphal.h"
|
||||
#include "py/mperrno.h"
|
||||
#include "py/stream.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
#include "machine_uart.h"
|
||||
#include "rtdevice.h"
|
||||
|
||||
#ifdef MICROPYTHON_USING_MACHINE_UART
|
||||
|
||||
#ifndef RT_USING_SERIAL
|
||||
#error "Please define the RT_USING_SERIAL on 'rtconfig.h'"
|
||||
#endif
|
||||
|
||||
typedef struct _machine_uart_obj_t {
|
||||
mp_obj_base_t base;
|
||||
struct rt_serial_device *uart_device;
|
||||
}machine_uart_obj_t;
|
||||
|
||||
STATIC void machine_uart_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
|
||||
machine_uart_obj_t *self = (machine_uart_obj_t*) self_in;
|
||||
mp_printf(print, "uart( device port : %s,baud_rate = %d, data_bits = %d, parity = %d, stop_bits = %d )",
|
||||
self->uart_device->parent.parent.name,
|
||||
self->uart_device->config.baud_rate,
|
||||
self->uart_device->config.data_bits,
|
||||
self->uart_device->config.parity,
|
||||
self->uart_device->config.stop_bits);
|
||||
}
|
||||
|
||||
STATIC mp_obj_t machine_uart_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
|
||||
mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true);
|
||||
char uart_dev_name[RT_NAME_MAX];
|
||||
snprintf(uart_dev_name, sizeof(uart_dev_name), "uart%d", mp_obj_get_int(args[0]));
|
||||
|
||||
struct rt_serial_device *rt_serial_device = (struct rt_serial_device *) rt_device_find(uart_dev_name);
|
||||
if (rt_serial_device == RT_NULL || rt_serial_device->parent.type != RT_Device_Class_Char) {
|
||||
mp_printf(&mp_plat_print, "ERROR: UART device %s not found!\n", uart_dev_name);
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "UART(%s) doesn't exist", uart_dev_name));
|
||||
}
|
||||
|
||||
rt_err_t result;
|
||||
result = rt_device_open((rt_device_t)rt_serial_device, RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_INT_RX );
|
||||
if (result != RT_EOK)
|
||||
{
|
||||
mp_printf(&mp_plat_print, "ERROR: UART device %s can't open!\n", uart_dev_name);
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "UART(%s) can't open", uart_dev_name));
|
||||
}
|
||||
|
||||
// create new uart object
|
||||
machine_uart_obj_t *self = m_new_obj(machine_uart_obj_t);
|
||||
self->base.type = &machine_uart_type;
|
||||
self->uart_device = rt_serial_device;
|
||||
return (mp_obj_t) self;
|
||||
}
|
||||
|
||||
/// \method init(baudrate, bits=8, parity=None, stop=1, *, timeout=1000, timeout_char=0, flow=0, read_buf_len=64)
|
||||
///
|
||||
/// Initialise the UART bus with the given parameters:
|
||||
///
|
||||
/// - `baudrate` is the clock rate.
|
||||
/// - `bits` is the number of bits per byte, 7, 8 or 9.
|
||||
/// - `parity` is the parity, `None`, 0 (even) or 1 (odd).
|
||||
/// - `stop` is the number of stop bits, 1 or 2.
|
||||
/// - `timeout` is the timeout in milliseconds to wait for the first character.
|
||||
/// - `timeout_char` is the timeout in milliseconds to wait between characters.
|
||||
/// - `flow` is RTS | CTS where RTS == 256, CTS == 512
|
||||
/// - `read_buf_len` is the character length of the read buffer (0 to disable).
|
||||
///
|
||||
STATIC mp_obj_t machine_uart_init_helper(machine_uart_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{ MP_QSTR_baudrate, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 9600} },
|
||||
{ MP_QSTR_bits, MP_ARG_INT, {.u_int = 8} },
|
||||
{ MP_QSTR_parity, MP_ARG_OBJ, {.u_obj = mp_const_none} },
|
||||
{ MP_QSTR_stop, MP_ARG_INT, {.u_int = 1} },
|
||||
{ MP_QSTR_flow, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, // rt-thread does not support
|
||||
{ MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1000} },
|
||||
{ MP_QSTR_timeout_char, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
|
||||
{ MP_QSTR_read_buf_len, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 64} },
|
||||
};
|
||||
|
||||
// parse args
|
||||
struct {
|
||||
mp_arg_val_t baudrate, bits, parity, stop, flow, timeout, timeout_char, read_buf_len;
|
||||
} args;
|
||||
mp_arg_parse_all(n_args, pos_args, kw_args,
|
||||
MP_ARRAY_SIZE(allowed_args), allowed_args, (mp_arg_val_t*)&args);
|
||||
|
||||
// set the UART configuration values
|
||||
struct rt_serial_device *uart_p = self->uart_device;
|
||||
struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
|
||||
|
||||
// baudrate
|
||||
config.baud_rate = args.baudrate.u_int;
|
||||
|
||||
// parity
|
||||
mp_int_t bits = args.bits.u_int;
|
||||
if (args.parity.u_obj == mp_const_none) {
|
||||
config.parity = PARITY_NONE;
|
||||
} else {
|
||||
mp_int_t parity = mp_obj_get_int(args.parity.u_obj);
|
||||
config.parity = (parity & 1) ? PARITY_ODD : PARITY_EVEN;
|
||||
//bits += 1; // STs convention has bits including parity, not all mcu
|
||||
}
|
||||
|
||||
// number of bits
|
||||
if (bits == 8) {
|
||||
config.data_bits = DATA_BITS_8;
|
||||
} else if (bits == 9) {
|
||||
config.data_bits = DATA_BITS_9;
|
||||
} else if (bits == 7) {
|
||||
config.data_bits = DATA_BITS_7;
|
||||
} else {
|
||||
mp_raise_ValueError("unsupported combination of bits and parity");
|
||||
}
|
||||
|
||||
// stop bits
|
||||
switch (args.stop.u_int) {
|
||||
case 1: config.stop_bits = STOP_BITS_1; break;
|
||||
default: config.stop_bits = STOP_BITS_2; break;
|
||||
}
|
||||
|
||||
//buffer size
|
||||
#if defined(RT_USING_SERIAL_V1)
|
||||
config.bufsz = args.read_buf_len.u_int;
|
||||
|
||||
#elif defined(RT_USING_SERIAL_V2)
|
||||
config.rx_bufsz = args.read_buf_len.u_int;
|
||||
config.tx_bufsz = args.read_buf_len.u_int;
|
||||
#endif
|
||||
rt_device_control((struct rt_device *) uart_p, RT_DEVICE_CTRL_CONFIG, &config);
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
|
||||
STATIC mp_obj_t machine_uart_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
|
||||
return machine_uart_init_helper(args[0], n_args - 1, args + 1, kw_args);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_uart_init_obj, 1, machine_uart_init);
|
||||
|
||||
STATIC mp_obj_t machine_uart_deinit(mp_obj_t self_in) {
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_uart_deinit_obj, machine_uart_deinit);
|
||||
|
||||
#define RETRY_TIMES 500
|
||||
|
||||
STATIC mp_obj_t machine_uart_writechar(mp_obj_t self_in, mp_obj_t char_in) {
|
||||
machine_uart_obj_t *self = self_in;
|
||||
uint16_t data = mp_obj_get_int(char_in);
|
||||
rt_size_t len = 0;
|
||||
rt_uint32_t timeout = 0;
|
||||
do
|
||||
{
|
||||
len = rt_device_write((struct rt_device *)(self->uart_device), 0, &data, 1);
|
||||
timeout++;
|
||||
}
|
||||
while (len != 1 && timeout < RETRY_TIMES);
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(machine_uart_writechar_obj, machine_uart_writechar);
|
||||
|
||||
#define UART_RX_EVENT (1 << 0)
|
||||
static struct rt_event event;
|
||||
|
||||
STATIC mp_obj_t machine_uart_readchar(mp_obj_t self_in) {
|
||||
machine_uart_obj_t *self = self_in;
|
||||
rt_uint32_t e;
|
||||
rt_uint8_t ch;
|
||||
|
||||
while (rt_device_read((struct rt_device *)(self->uart_device), 0, &ch, 1) != 1) {
|
||||
rt_event_recv(&event, UART_RX_EVENT, RT_EVENT_FLAG_AND |
|
||||
RT_EVENT_FLAG_CLEAR, RT_WAITING_FOREVER, &e);
|
||||
}
|
||||
|
||||
return MP_OBJ_NEW_SMALL_INT(ch);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_uart_readchar_obj, machine_uart_readchar);
|
||||
|
||||
STATIC const mp_rom_map_elem_t machine_uart_locals_dict_table[] = {
|
||||
// instance methods
|
||||
|
||||
{ MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_uart_init_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_uart_deinit_obj) },
|
||||
// { MP_ROM_QSTR(MP_QSTR_any), MP_ROM_PTR(&machine_uart_any_obj) },
|
||||
|
||||
/// \method read([nbytes])
|
||||
{ MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) },
|
||||
/// \method readline()
|
||||
{ MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj)},
|
||||
/// \method readinto(buf[, nbytes])
|
||||
{ MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) },
|
||||
/// \method write(buf)
|
||||
{ MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) },
|
||||
|
||||
{ MP_ROM_QSTR(MP_QSTR_writechar), MP_ROM_PTR(&machine_uart_writechar_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_readchar), MP_ROM_PTR(&machine_uart_readchar_obj) },
|
||||
// { MP_ROM_QSTR(MP_QSTR_sendbreak), MP_ROM_PTR(&pyb_uart_sendbreak_obj) },
|
||||
|
||||
// class constants
|
||||
// { MP_ROM_QSTR(MP_QSTR_RTS), MP_ROM_INT(UART_HWCONTROL_RTS) },
|
||||
// { MP_ROM_QSTR(MP_QSTR_CTS), MP_ROM_INT(UART_HWCONTROL_CTS) },
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(machine_uart_locals_dict, machine_uart_locals_dict_table);
|
||||
|
||||
STATIC mp_uint_t machine_uart_read(mp_obj_t self_in, void *buf_in, mp_uint_t size, int *errcode) {
|
||||
machine_uart_obj_t *self = self_in;
|
||||
byte *buf = buf_in;
|
||||
//TODO dfs sync read
|
||||
//MP_RTT_NOT_IMPL_PRINT;
|
||||
return rt_device_read((struct rt_device *)(self->uart_device), -1, buf, size);
|
||||
}
|
||||
|
||||
STATIC mp_uint_t machine_uart_write(mp_obj_t self_in, const void *buf_in, mp_uint_t size, int *errcode) {
|
||||
machine_uart_obj_t *self = self_in;
|
||||
const byte *buf = buf_in;
|
||||
//TODO dfs sync write
|
||||
//MP_RTT_NOT_IMPL_PRINT;
|
||||
return rt_device_write((struct rt_device *)(self->uart_device), -1, buf, size);
|
||||
}
|
||||
|
||||
STATIC mp_uint_t machine_uart_ioctl(mp_obj_t obj, mp_uint_t request, uintptr_t arg, int *errcode) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
STATIC const mp_stream_p_t uart_stream_p = {
|
||||
.read = machine_uart_read,
|
||||
.write = machine_uart_write,
|
||||
.ioctl = machine_uart_ioctl,
|
||||
.is_text = false,
|
||||
};
|
||||
|
||||
const mp_obj_type_t machine_uart_type = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_UART,
|
||||
.print = machine_uart_print,
|
||||
.make_new = machine_uart_make_new,
|
||||
.getiter = mp_identity_getiter,
|
||||
.iternext = mp_stream_unbuffered_iter,
|
||||
.protocol = &uart_stream_p,
|
||||
.locals_dict = (mp_obj_dict_t*)&machine_uart_locals_dict,
|
||||
};
|
||||
|
||||
#endif // MICROPYTHON_USING_MACHINE_UART
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 SummerGift <zhangyuan@rt-thread.com>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef MICROPY_INCLUDED_MACHINE_UART_H
|
||||
#define MICROPY_INCLUDED_MACHINE_UART_H
|
||||
|
||||
#include "py/obj.h"
|
||||
#include <rtthread.h>
|
||||
|
||||
extern const mp_obj_type_t machine_uart_type;
|
||||
|
||||
#endif // _MACHINE_UART_H
|
||||
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2019 ChenYong (chenyong@rt-thread.com)
|
||||
*
|
||||
* 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 <string.h>
|
||||
|
||||
#include "py/nlr.h"
|
||||
#include "py/obj.h"
|
||||
#include "py/runtime.h"
|
||||
#include "modmachine.h"
|
||||
#include "mphalport.h"
|
||||
|
||||
#ifdef MICROPYTHON_USING_MACHINE_WDT
|
||||
|
||||
#include <rtthread.h>
|
||||
#include <drivers/watchdog.h>
|
||||
#include "machine_wdt.h"
|
||||
|
||||
typedef struct _machine_wdt_obj_t {
|
||||
mp_obj_base_t base;
|
||||
rt_device_t wdt_device;
|
||||
}machine_wdt_obj_t;
|
||||
|
||||
const mp_obj_type_t machine_wdt_type;
|
||||
|
||||
STATIC void error_check(bool status, const char *msg) {
|
||||
if (!status) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, msg));
|
||||
}
|
||||
}
|
||||
|
||||
STATIC mp_obj_t machine_wdt_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {
|
||||
#define MP_WDT_DEV_NAME "wdt"
|
||||
machine_wdt_obj_t *self = m_new_obj(machine_wdt_obj_t);
|
||||
char wdt_dev_name[RT_NAME_MAX] = {0};
|
||||
rt_err_t result = RT_EOK;
|
||||
mp_int_t timeout = 5;
|
||||
|
||||
// check arguments
|
||||
mp_arg_check_num(n_args, n_kw, 0, 2, false);
|
||||
|
||||
if (n_args == 2) {
|
||||
// check input WDT device name or ID
|
||||
if (mp_obj_is_small_int(args[0])) {
|
||||
rt_snprintf(wdt_dev_name, sizeof(wdt_dev_name), "wdt%d", mp_obj_get_int(args[0]));
|
||||
} else if (mp_obj_is_qstr(args[0])) {
|
||||
rt_strncpy(wdt_dev_name, mp_obj_str_get_str(args[0]), RT_NAME_MAX);
|
||||
} else {
|
||||
error_check(0, "Input WDT device name or ID error.");
|
||||
}
|
||||
timeout = mp_obj_get_int(args[1]);
|
||||
error_check(timeout >= 1, "input timeout value error");
|
||||
} else if (n_args == 1) {
|
||||
if (mp_obj_is_small_int(args[0])) {
|
||||
timeout = mp_obj_get_int(args[0]);
|
||||
error_check(timeout >= 1, "input timeout value error");
|
||||
} else if (mp_obj_is_qstr(args[0])) {
|
||||
rt_strncpy(wdt_dev_name, mp_obj_str_get_str(args[0]), RT_NAME_MAX);
|
||||
} else {
|
||||
error_check(0, "Input WDT device name or ID error.");
|
||||
}
|
||||
} else {
|
||||
rt_strncpy(wdt_dev_name, MP_WDT_DEV_NAME, RT_NAME_MAX);
|
||||
}
|
||||
|
||||
self->base.type = &machine_wdt_type;
|
||||
// find WDT device
|
||||
self->wdt_device = rt_device_find(wdt_dev_name);
|
||||
if (self->wdt_device == RT_NULL || self->wdt_device->type != RT_Device_Class_Miscellaneous) {
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "WDT(%s) don't exist", wdt_dev_name));
|
||||
}
|
||||
|
||||
result = rt_device_init(self->wdt_device);
|
||||
error_check(result == RT_EOK, "WDT init error");
|
||||
|
||||
// set WDT device timout
|
||||
result = rt_device_control(self->wdt_device, RT_DEVICE_CTRL_WDT_SET_TIMEOUT, (void *)&timeout);
|
||||
error_check(result == RT_EOK, "WDT set timout error");
|
||||
|
||||
result = rt_device_control(self->wdt_device, RT_DEVICE_CTRL_WDT_START, RT_NULL);
|
||||
error_check(result == RT_EOK, "WDT start error");
|
||||
|
||||
// return constant object
|
||||
return MP_OBJ_FROM_PTR(self);
|
||||
}
|
||||
|
||||
STATIC mp_obj_t machine_wdt_feed(mp_obj_t self_in) {
|
||||
/* idle task feed */
|
||||
machine_wdt_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
rt_err_t result = RT_EOK;
|
||||
|
||||
result = rt_device_control(self->wdt_device, RT_DEVICE_CTRL_WDT_KEEPALIVE, RT_NULL);
|
||||
error_check(result == RT_EOK, "WDT feed failed");
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_wdt_feed_obj, machine_wdt_feed);
|
||||
|
||||
STATIC const mp_rom_map_elem_t machine_wdt_locals_dict_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR_feed), MP_ROM_PTR(&machine_wdt_feed_obj) },
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(machine_wdt_locals_dict, machine_wdt_locals_dict_table);
|
||||
|
||||
const mp_obj_type_t machine_wdt_type = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_WDT,
|
||||
.make_new = machine_wdt_make_new,
|
||||
.locals_dict = (mp_obj_t) &machine_wdt_locals_dict,
|
||||
};
|
||||
|
||||
#endif // MICROPYTHON_USING_MACHINE_WDT
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2019 ChenYong (chenyong@rt-thread.com)
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef MICROPY_INCLUDED_MACHINE_WDT_H
|
||||
#define MICROPY_INCLUDED_MACHINE_WDT_H
|
||||
|
||||
#include "py/obj.h"
|
||||
#include <rtthread.h>
|
||||
|
||||
extern const mp_obj_type_t machine_wdt_type;
|
||||
|
||||
#endif // MICROPY_INCLUDED_MACHINE_WDT_H
|
||||
|
||||
@@ -0,0 +1,260 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Armink (armink.ztl@gmail.com)
|
||||
*
|
||||
* 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 <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "py/obj.h"
|
||||
#include "py/runtime.h"
|
||||
#include "py/gc.h"
|
||||
#include "lib/utils/pyexec.h"
|
||||
#include "extmod/machine_mem.h"
|
||||
#include "extmod/machine_signal.h"
|
||||
#include "extmod/machine_pulse.h"
|
||||
#include "extmod/machine_i2c.h"
|
||||
#include "extmod/machine_spi.h"
|
||||
#include "modmachine.h"
|
||||
#include "machine_uart.h"
|
||||
#include "machine_adc.h"
|
||||
#include "machine_pwm.h"
|
||||
#include "machine_lcd.h"
|
||||
#include "machine_rtc.h"
|
||||
#include "machine_wdt.h"
|
||||
#include "machine_timer.h"
|
||||
|
||||
#include <rthw.h>
|
||||
|
||||
#if MICROPY_PY_MACHINE
|
||||
|
||||
STATIC mp_obj_t machine_info(size_t n_args, const mp_obj_t *args) {
|
||||
#ifdef RT_USING_FINSH
|
||||
extern long list_thread(void);
|
||||
#endif
|
||||
// RT-Thread info
|
||||
{
|
||||
mp_printf(&mp_plat_print, "---------------------------------------------\n");
|
||||
mp_printf(&mp_plat_print, "RT-Thread\n");
|
||||
mp_printf(&mp_plat_print, "---------------------------------------------\n");
|
||||
|
||||
#ifdef RT_USING_FINSH
|
||||
extern void list_mem(void);
|
||||
extern void list_memheap(void);
|
||||
|
||||
#ifdef RT_USING_MEMHEAP_AS_HEAP
|
||||
list_memheap();
|
||||
#else
|
||||
list_mem();
|
||||
#endif
|
||||
|
||||
list_thread();
|
||||
#endif
|
||||
mp_printf(&mp_plat_print, "---------------------------------------------\n");
|
||||
}
|
||||
|
||||
// qstr info
|
||||
{
|
||||
mp_uint_t n_pool, n_qstr, n_str_data_bytes, n_total_bytes;
|
||||
qstr_pool_info(&n_pool, &n_qstr, &n_str_data_bytes, &n_total_bytes);
|
||||
mp_printf(&mp_plat_print, "qstr:\n n_pool=" UINT_FMT "\n n_qstr=" UINT_FMT "\n n_str_data_bytes=" UINT_FMT "\n n_total_bytes=" UINT_FMT "\n", n_pool, n_qstr, n_str_data_bytes, n_total_bytes);
|
||||
}
|
||||
mp_printf(&mp_plat_print, "---------------------------------------------\n");
|
||||
|
||||
// GC info
|
||||
{
|
||||
gc_info_t info;
|
||||
gc_info(&info);
|
||||
mp_printf(&mp_plat_print, "GC:\n");
|
||||
mp_printf(&mp_plat_print, " " UINT_FMT " total\n", info.total);
|
||||
mp_printf(&mp_plat_print, " " UINT_FMT " : " UINT_FMT "\n", info.used, info.free);
|
||||
mp_printf(&mp_plat_print, " 1=" UINT_FMT " 2=" UINT_FMT " m=" UINT_FMT "\n", info.num_1block, info.num_2block, info.max_block);
|
||||
}
|
||||
|
||||
// free space on flash
|
||||
{
|
||||
//TODO
|
||||
}
|
||||
|
||||
if (n_args == 1) {
|
||||
// arg given means dump gc allocation table
|
||||
gc_dump_alloc_table();
|
||||
}
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_info_obj, 0, 1, machine_info);
|
||||
|
||||
STATIC mp_obj_t machine_unique_id(void) {
|
||||
//TODO
|
||||
MP_RTT_NOT_IMPL_PRINT;
|
||||
return 0;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_0(machine_unique_id_obj, machine_unique_id);
|
||||
|
||||
STATIC mp_obj_t machine_reset(void) {
|
||||
//TODO
|
||||
MP_RTT_NOT_IMPL_PRINT;
|
||||
return mp_const_none;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_0(machine_reset_obj, machine_reset);
|
||||
|
||||
STATIC mp_obj_t machine_soft_reset(void) {
|
||||
pyexec_system_exit = PYEXEC_FORCED_EXIT;
|
||||
nlr_raise(mp_obj_new_exception(&mp_type_SystemExit));
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_0(machine_soft_reset_obj, machine_soft_reset);
|
||||
|
||||
/*
|
||||
* @param clkid - range 0~127 (e.g 0:SYSCLK 1:HCLK 2:PCLK1 etc)
|
||||
*
|
||||
* @return 0 - ok, -1 - no such clock
|
||||
*/
|
||||
RT_WEAK int mp_port_get_freq(int clkid, int *freq)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
STATIC mp_obj_t machine_freq(void) {
|
||||
int i;
|
||||
mp_obj_list_t *ret_list = m_new(mp_obj_list_t, 1);
|
||||
mp_obj_list_init(ret_list, 0);
|
||||
int freq;
|
||||
|
||||
for (i = 0; i < 128; i ++)
|
||||
{
|
||||
if (mp_port_get_freq(i, &freq) != 0)
|
||||
break;
|
||||
|
||||
mp_obj_list_append(ret_list, mp_obj_new_int(freq));
|
||||
}
|
||||
|
||||
return MP_OBJ_FROM_PTR(ret_list);
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_0(machine_freq_obj, machine_freq);
|
||||
|
||||
STATIC mp_obj_t pyb_wfi(void) {
|
||||
//TODO __WFI();
|
||||
MP_RTT_NOT_IMPL_PRINT;
|
||||
return mp_const_none;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_0(pyb_wfi_obj, pyb_wfi);
|
||||
|
||||
static rt_base_t int_lvl;
|
||||
STATIC mp_obj_t pyb_disable_irq(void) {
|
||||
int_lvl = rt_hw_interrupt_disable();
|
||||
return mp_obj_new_bool(1);
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_0(pyb_disable_irq_obj, pyb_disable_irq);
|
||||
|
||||
STATIC mp_obj_t pyb_enable_irq(size_t n_args, const mp_obj_t *arg) {
|
||||
if (n_args == 0) {
|
||||
rt_hw_interrupt_enable(int_lvl);
|
||||
} else {
|
||||
if (mp_obj_is_true(arg[0])) {
|
||||
rt_hw_interrupt_enable(int_lvl);
|
||||
} else {
|
||||
int_lvl = rt_hw_interrupt_disable();
|
||||
}
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_enable_irq_obj, 0, 1, pyb_enable_irq);
|
||||
|
||||
STATIC mp_obj_t machine_sleep (void) {
|
||||
//TODO
|
||||
MP_RTT_NOT_IMPL_PRINT;
|
||||
return mp_const_none;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_0(machine_sleep_obj, machine_sleep);
|
||||
|
||||
STATIC mp_obj_t machine_deepsleep (void) {
|
||||
//TODO
|
||||
MP_RTT_NOT_IMPL_PRINT;
|
||||
return mp_const_none;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_0(machine_deepsleep_obj, machine_deepsleep);
|
||||
|
||||
STATIC mp_obj_t machine_reset_cause(void) {
|
||||
//TODO
|
||||
MP_RTT_NOT_IMPL_PRINT;
|
||||
return MP_OBJ_NEW_SMALL_INT(42);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_reset_cause_obj, machine_reset_cause);
|
||||
|
||||
STATIC const mp_rom_map_elem_t machine_module_globals_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_umachine) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_info), MP_ROM_PTR(&machine_info_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_unique_id), MP_ROM_PTR(&machine_unique_id_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_reset), MP_ROM_PTR(&machine_reset_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_soft_reset), MP_ROM_PTR(&machine_soft_reset_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_freq), MP_ROM_PTR(&machine_freq_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_idle), MP_ROM_PTR(&pyb_wfi_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_sleep), MP_ROM_PTR(&machine_sleep_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_deepsleep), MP_ROM_PTR(&machine_deepsleep_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_reset_cause), MP_ROM_PTR(&machine_reset_cause_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_disable_irq), MP_ROM_PTR(&pyb_disable_irq_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_enable_irq), MP_ROM_PTR(&pyb_enable_irq_obj) },
|
||||
// { MP_ROM_QSTR(MP_QSTR_time_pulse_us), MP_ROM_PTR(&machine_time_pulse_us_obj) },
|
||||
#if MICROPY_PY_PIN
|
||||
{ MP_ROM_QSTR(MP_QSTR_Pin), MP_ROM_PTR(&machine_pin_type) },
|
||||
#endif
|
||||
{ MP_ROM_QSTR(MP_QSTR_Signal), MP_ROM_PTR(&machine_signal_type) },
|
||||
#if MICROPY_PY_MACHINE_I2C
|
||||
{ MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&machine_i2c_type) },
|
||||
#endif
|
||||
#if MICROPY_PY_MACHINE_SPI
|
||||
{ MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&mp_machine_soft_spi_type) },
|
||||
#endif
|
||||
#if MICROPY_PY_MACHINE_UART
|
||||
{ MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&machine_uart_type) },
|
||||
#endif
|
||||
#if MICROPY_PY_MACHINE_RTC
|
||||
{ MP_ROM_QSTR(MP_QSTR_RTC), MP_ROM_PTR(&machine_rtc_type) },
|
||||
#endif
|
||||
#if MICROPY_PY_MACHINE_LCD
|
||||
{ MP_ROM_QSTR(MP_QSTR_LCD), MP_ROM_PTR(&machine_lcd_type ) },
|
||||
#endif
|
||||
#if MICROPY_PY_MACHINE_PWM
|
||||
{ MP_ROM_QSTR(MP_QSTR_PWM), MP_ROM_PTR(&machine_pwm_type) },
|
||||
#endif
|
||||
#if MICROPY_PY_MACHINE_ADC
|
||||
{ MP_ROM_QSTR(MP_QSTR_ADC), MP_ROM_PTR(&machine_adc_type) },
|
||||
#endif
|
||||
#if MICROPY_PY_MACHINE_WDT
|
||||
{ MP_ROM_QSTR(MP_QSTR_WDT), MP_ROM_PTR(&machine_wdt_type) },
|
||||
#endif
|
||||
#if MICROPY_PY_MACHINE_TIMER
|
||||
{ MP_ROM_QSTR(MP_QSTR_Timer), MP_ROM_PTR(&machine_timer_type) },
|
||||
#endif
|
||||
};
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(machine_module_globals, machine_module_globals_table);
|
||||
|
||||
const mp_obj_module_t mp_module_machine = {
|
||||
.base = { &mp_type_module },
|
||||
.globals = (mp_obj_dict_t*)&machine_module_globals,
|
||||
};
|
||||
|
||||
#endif // MICROPY_PY_MACHINE
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Armink (armink.ztl@gmail.com)
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _MODMACHINE_H
|
||||
#define _MODMACHINE_H
|
||||
|
||||
#include "py/obj.h"
|
||||
#include <rtthread.h>
|
||||
|
||||
extern const mp_obj_type_t machine_pin_type;
|
||||
|
||||
MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(machine_info_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_0(machine_unique_id_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_0(machine_reset_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_0(machine_bootloader_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_0(machine_freq_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_0(pyb_wfi_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_0(pyb_disable_irq_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_enable_irq_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_0(machine_sleep_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_0(machine_deepsleep_obj);
|
||||
|
||||
typedef struct _machine_pin_obj_t {
|
||||
mp_obj_base_t base;
|
||||
char name[RT_NAME_MAX];
|
||||
uint32_t pin;
|
||||
mp_obj_t pin_isr_cb;
|
||||
} machine_pin_obj_t;
|
||||
|
||||
#endif // _MODMACHINE_H
|
||||
@@ -0,0 +1,525 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2013, 2014 Damien P. George
|
||||
* Copyright (c) 2014 Paul Sokolovsky
|
||||
* Copyright (c) 2019 Armink (armink.ztl@gmail.com)
|
||||
*
|
||||
* 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 <assert.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "py/runtime.h"
|
||||
#include "py/binary.h"
|
||||
#include "py/mperrno.h"
|
||||
|
||||
#ifdef MICROPYTHON_USING_FFI
|
||||
|
||||
#if !defined(__GNUC__)
|
||||
#error "The ffi module only supports GCC toolchain at present"
|
||||
#endif
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <dlmodule.h>
|
||||
|
||||
typedef enum {
|
||||
FFI_TYPE_UNKNOWN,
|
||||
FFI_TYPE_SCHAR,
|
||||
FFI_TYPE_UCHAR,
|
||||
FFI_TYPE_SSHORT,
|
||||
FFI_TYPE_USHORT,
|
||||
FFI_TYPE_SINT,
|
||||
FFI_TYPE_UINT,
|
||||
FFI_TYPE_SLONG,
|
||||
FFI_TYPE_ULONG,
|
||||
FFI_TYPE_SINT64,
|
||||
FFI_TYPE_UINT64,
|
||||
FFI_TYPE_FLOAT,
|
||||
FFI_TYPE_DOUBLE,
|
||||
FFI_TYPE_POINTER,
|
||||
FFI_TYPE_VOID,
|
||||
} ffi_type_t;
|
||||
|
||||
typedef struct _mp_obj_opaque_t {
|
||||
mp_obj_base_t base;
|
||||
void *val;
|
||||
} mp_obj_opaque_t;
|
||||
|
||||
typedef struct _mp_obj_ffimod_t {
|
||||
mp_obj_base_t base;
|
||||
void *handle;
|
||||
} mp_obj_ffimod_t;
|
||||
|
||||
typedef struct _mp_obj_ffivar_t {
|
||||
mp_obj_base_t base;
|
||||
void *var;
|
||||
char type;
|
||||
} mp_obj_ffivar_t;
|
||||
|
||||
typedef struct _mp_obj_ffifunc_t {
|
||||
mp_obj_base_t base;
|
||||
void *func;
|
||||
char rettype;
|
||||
uint32_t argc;
|
||||
const char *argtypes;
|
||||
ffi_type_t *params;
|
||||
} mp_obj_ffifunc_t;
|
||||
|
||||
typedef struct _mp_obj_fficallback_t {
|
||||
mp_obj_base_t base;
|
||||
void *func;
|
||||
char rettype;
|
||||
ffi_type_t *params;
|
||||
} mp_obj_fficallback_t;
|
||||
|
||||
typedef unsigned long ffi_arg;
|
||||
|
||||
STATIC const mp_obj_type_t ffimod_type;
|
||||
STATIC const mp_obj_type_t ffifunc_type;
|
||||
STATIC const mp_obj_type_t fficallback_type;
|
||||
STATIC const mp_obj_type_t ffivar_type;
|
||||
|
||||
STATIC ffi_type_t char2ffi_type(char c)
|
||||
{
|
||||
switch (c) {
|
||||
case 'b': return FFI_TYPE_SCHAR;
|
||||
case 'B': return FFI_TYPE_UCHAR;
|
||||
case 'h': return FFI_TYPE_SSHORT;
|
||||
case 'H': return FFI_TYPE_USHORT;
|
||||
case 'i': return FFI_TYPE_SINT;
|
||||
case 'I': return FFI_TYPE_UINT;
|
||||
case 'l': return FFI_TYPE_SLONG;
|
||||
case 'L': return FFI_TYPE_ULONG;
|
||||
case 'q': return FFI_TYPE_SINT64;
|
||||
case 'Q': return FFI_TYPE_UINT64;
|
||||
#if MICROPY_PY_BUILTINS_FLOAT
|
||||
case 'f': return FFI_TYPE_FLOAT;
|
||||
case 'd': return FFI_TYPE_DOUBLE;
|
||||
#endif
|
||||
case 'O': // mp_obj_t
|
||||
case 'C': // (*)()
|
||||
case 'P': // const void*
|
||||
case 'p': // void*
|
||||
case 's': return FFI_TYPE_POINTER;
|
||||
case 'v': return FFI_TYPE_VOID;
|
||||
default: return FFI_TYPE_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
STATIC ffi_type_t get_ffi_type(mp_obj_t o_in)
|
||||
{
|
||||
if (MP_OBJ_IS_STR(o_in)) {
|
||||
const char *s = mp_obj_str_get_str(o_in);
|
||||
ffi_type_t t = char2ffi_type(*s);
|
||||
if (t != FFI_TYPE_UNKNOWN) {
|
||||
return t;
|
||||
}
|
||||
}
|
||||
// TODO: Support actual libffi type objects
|
||||
|
||||
mp_raise_TypeError("Unknown type");
|
||||
}
|
||||
|
||||
STATIC mp_obj_t return_ffi_value(void *val, char type)
|
||||
{
|
||||
switch (type) {
|
||||
case 's': {
|
||||
const char *s = (const char *)(intptr_t)val;
|
||||
if (!s) {
|
||||
return mp_const_none;
|
||||
}
|
||||
return mp_obj_new_str(s, strlen(s));
|
||||
}
|
||||
case 'v':
|
||||
return mp_const_none;
|
||||
#if MICROPY_PY_BUILTINS_FLOAT
|
||||
case 'f': {
|
||||
union { void *ffi; float flt; } val_union = { .ffi = val };
|
||||
return mp_obj_new_float(val_union.flt);
|
||||
}
|
||||
case 'd': {
|
||||
double *p = (double*)&val;
|
||||
mp_raise_NotImplementedError("The double return type NOT supported");
|
||||
return mp_obj_new_float(*p);
|
||||
}
|
||||
#endif
|
||||
case 'O':
|
||||
return (mp_obj_t)(intptr_t)val;
|
||||
default:
|
||||
return mp_obj_new_int((mp_int_t)val);
|
||||
}
|
||||
}
|
||||
|
||||
// FFI module
|
||||
|
||||
STATIC void ffimod_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
|
||||
(void)kind;
|
||||
mp_obj_ffimod_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
mp_printf(print, "<ffimod %p>", self->handle);
|
||||
}
|
||||
|
||||
STATIC mp_obj_t ffimod_close(mp_obj_t self_in) {
|
||||
mp_obj_ffimod_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
|
||||
dlclose(self->handle);
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(ffimod_close_obj, ffimod_close);
|
||||
|
||||
STATIC mp_obj_t make_func(mp_obj_t rettype_in, void *func, mp_obj_t argtypes_in) {
|
||||
const char *rettype = mp_obj_str_get_str(rettype_in);
|
||||
const char *argtypes = mp_obj_str_get_str(argtypes_in);
|
||||
|
||||
mp_int_t nparams = MP_OBJ_SMALL_INT_VALUE(mp_obj_len_maybe(argtypes_in));
|
||||
mp_obj_ffifunc_t *o = m_new_obj_var(mp_obj_ffifunc_t, ffi_type_t, nparams);
|
||||
o->base.type = &ffifunc_type;
|
||||
o->func = func;
|
||||
o->rettype = *rettype;
|
||||
o->argtypes = argtypes;
|
||||
o->argc = nparams;
|
||||
o->params = (uint8_t *)o + sizeof(mp_obj_ffifunc_t);
|
||||
|
||||
mp_obj_iter_buf_t iter_buf;
|
||||
mp_obj_t iterable = mp_getiter(argtypes_in, &iter_buf);
|
||||
mp_obj_t item;
|
||||
int i = 0;
|
||||
while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) {
|
||||
o->params[i++] = get_ffi_type(item);
|
||||
}
|
||||
/* when param is void change the argc to 0 */
|
||||
if (o->argc == 1 && o->params[0] == FFI_TYPE_VOID) {
|
||||
o->argc = 0;
|
||||
}
|
||||
|
||||
return MP_OBJ_FROM_PTR(o);
|
||||
}
|
||||
|
||||
STATIC mp_obj_t ffimod_func(size_t n_args, const mp_obj_t *args) {
|
||||
(void)n_args; // always 4
|
||||
mp_obj_ffimod_t *self = MP_OBJ_TO_PTR(args[0]);
|
||||
const char *symname = mp_obj_str_get_str(args[2]);
|
||||
|
||||
void *sym = dlsym(self->handle, symname);
|
||||
if (sym == NULL) {
|
||||
mp_raise_ValueError("input symbol NOT found");
|
||||
}
|
||||
return make_func(args[1], sym, args[3]);
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(ffimod_func_obj, 4, 4, ffimod_func);
|
||||
|
||||
STATIC mp_obj_t mod_ffi_func(mp_obj_t rettype, mp_obj_t addr_in, mp_obj_t argtypes) {
|
||||
void *addr;
|
||||
/* find the built-in function address when address is string type */
|
||||
if (mp_obj_is_str(addr_in)) {
|
||||
addr = (void *) dlmodule_symbol_find(mp_obj_str_get_str(addr_in));
|
||||
if (addr == NULL) {
|
||||
mp_raise_ValueError("input symbol NOT found");
|
||||
}
|
||||
} else {
|
||||
addr = (void*) MP_OBJ_TO_PTR(mp_obj_int_get_truncated(addr_in));
|
||||
}
|
||||
|
||||
return make_func(rettype, addr, argtypes);
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_3(mod_ffi_func_obj, mod_ffi_func);
|
||||
|
||||
STATIC void call_py_func(void *ret, int argc, void** args, void *func) {
|
||||
mp_obj_t *pyargs = m_new(mp_obj_t, argc);
|
||||
for (int i = 0; i < argc; i++) {
|
||||
pyargs[i] = mp_obj_new_int(*(mp_int_t*)args[i]);
|
||||
}
|
||||
mp_obj_t res = mp_call_function_n_kw(MP_OBJ_FROM_PTR(func), argc, 0, pyargs);
|
||||
|
||||
m_free(pyargs);
|
||||
|
||||
if (res != mp_const_none) {
|
||||
*(ffi_arg*)ret = mp_obj_int_get_truncated(res);
|
||||
}
|
||||
}
|
||||
|
||||
STATIC mp_obj_t mod_ffi_callback(mp_obj_t rettype_in, mp_obj_t func_in, mp_obj_t paramtypes_in) {
|
||||
const char *rettype = mp_obj_str_get_str(rettype_in);
|
||||
|
||||
mp_int_t nparams = MP_OBJ_SMALL_INT_VALUE(mp_obj_len_maybe(paramtypes_in));
|
||||
|
||||
mp_obj_fficallback_t *o = m_new_obj_var(mp_obj_fficallback_t, ffi_type_t, nparams);
|
||||
|
||||
//TODO add callback impl
|
||||
mp_raise_NotImplementedError("The callback NOT supported");
|
||||
|
||||
return MP_OBJ_FROM_PTR(o);
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_3(mod_ffi_callback_obj, mod_ffi_callback);
|
||||
|
||||
STATIC mp_obj_t ffimod_var(mp_obj_t self_in, mp_obj_t vartype_in, mp_obj_t symname_in) {
|
||||
mp_obj_ffimod_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
const char *rettype = mp_obj_str_get_str(vartype_in);
|
||||
const char *symname = mp_obj_str_get_str(symname_in);
|
||||
|
||||
void *sym = dlsym(self->handle, symname);
|
||||
if (sym == NULL) {
|
||||
mp_raise_OSError(MP_ENOENT);
|
||||
}
|
||||
mp_obj_ffivar_t *o = m_new_obj(mp_obj_ffivar_t);
|
||||
o->base.type = &ffivar_type;
|
||||
|
||||
o->var = sym;
|
||||
o->type = *rettype;
|
||||
return MP_OBJ_FROM_PTR(o);
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_3(ffimod_var_obj, ffimod_var);
|
||||
|
||||
STATIC mp_obj_t ffimod_addr(mp_obj_t self_in, mp_obj_t symname_in) {
|
||||
mp_obj_ffimod_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
const char *symname = mp_obj_str_get_str(symname_in);
|
||||
|
||||
void *sym = dlsym(self->handle, symname);
|
||||
if (sym == NULL) {
|
||||
mp_raise_OSError(MP_ENOENT);
|
||||
}
|
||||
return mp_obj_new_int((uintptr_t)sym);
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_2(ffimod_addr_obj, ffimod_addr);
|
||||
|
||||
STATIC mp_obj_t ffimod_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
|
||||
(void)n_args;
|
||||
(void)n_kw;
|
||||
|
||||
const char *fname = NULL;
|
||||
if (args[0] != mp_const_none) {
|
||||
fname = mp_obj_str_get_str(args[0]);
|
||||
}
|
||||
void *mod = dlopen(fname, RTLD_NOW | RTLD_LOCAL);
|
||||
|
||||
if (mod == NULL) {
|
||||
mp_raise_OSError(errno);
|
||||
}
|
||||
mp_obj_ffimod_t *o = m_new_obj(mp_obj_ffimod_t);
|
||||
o->base.type = type;
|
||||
o->handle = mod;
|
||||
return MP_OBJ_FROM_PTR(o);
|
||||
}
|
||||
|
||||
STATIC const mp_rom_map_elem_t ffimod_locals_dict_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR_func), MP_ROM_PTR(&ffimod_func_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_var), MP_ROM_PTR(&ffimod_var_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_addr), MP_ROM_PTR(&ffimod_addr_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&ffimod_close_obj) },
|
||||
};
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(ffimod_locals_dict, ffimod_locals_dict_table);
|
||||
|
||||
STATIC const mp_obj_type_t ffimod_type = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_ffimod,
|
||||
.print = ffimod_print,
|
||||
.make_new = ffimod_make_new,
|
||||
.locals_dict = (mp_obj_dict_t*)&ffimod_locals_dict,
|
||||
};
|
||||
|
||||
// FFI function
|
||||
|
||||
STATIC void ffifunc_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
|
||||
(void)kind;
|
||||
mp_obj_ffifunc_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
mp_printf(print, "<ffifunc %p>", self->func);
|
||||
}
|
||||
|
||||
STATIC void ffi_call(void *func, ffi_arg *retval, uint32_t argc, ffi_arg *argv)
|
||||
{
|
||||
typedef ffi_arg(*f6_t)(ffi_arg, ffi_arg, ffi_arg, ffi_arg, ffi_arg, ffi_arg);
|
||||
|
||||
ffi_arg dummy = 0;
|
||||
ffi_arg args[6];
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < sizeof(args) / sizeof(args[0]); i ++) {
|
||||
if (i < argc) {
|
||||
args[i] = argv[i];
|
||||
} else {
|
||||
args[i] = (ffi_arg)&dummy;
|
||||
}
|
||||
}
|
||||
|
||||
*retval = ((f6_t)(func))(args[0], args[1], args[2], args[3], args[4], args[5]);
|
||||
}
|
||||
|
||||
STATIC mp_obj_t ffifunc_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {
|
||||
(void)n_kw;
|
||||
mp_obj_ffifunc_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
assert(n_kw == 0);
|
||||
|
||||
if (self->argc > n_args) {
|
||||
mp_raise_ValueError("input function parameter number mismatch");
|
||||
}
|
||||
|
||||
ffi_arg *values = m_new(ffi_arg, n_args);
|
||||
const char *argtype = self->argtypes;
|
||||
for (uint i = 0; i < n_args; i++, argtype++) {
|
||||
mp_obj_t a = args[i];
|
||||
if (*argtype == 'O') {
|
||||
values[i] = (ffi_arg)(intptr_t)a;
|
||||
#if MICROPY_PY_BUILTINS_FLOAT
|
||||
} else if (*argtype == 'f') {
|
||||
float *p = (float*)&values[i];
|
||||
*p = mp_obj_get_float(a);
|
||||
} else if (*argtype == 'd') {
|
||||
double *p = (double*)&values[i];
|
||||
*p = mp_obj_get_float(a);
|
||||
//TODO add double and long long supported
|
||||
mp_raise_NotImplementedError("The double parameter NOT supported");
|
||||
#endif
|
||||
} else if (a == mp_const_none) {
|
||||
values[i] = 0;
|
||||
} else if (mp_obj_is_int(a)) {
|
||||
values[i] = mp_obj_int_get_truncated(a);
|
||||
} else if (mp_obj_is_str(a)) {
|
||||
const char *s = mp_obj_str_get_str(a);
|
||||
values[i] = (ffi_arg)(intptr_t)s;
|
||||
} else if (((mp_obj_base_t*)MP_OBJ_TO_PTR(a))->type->buffer_p.get_buffer != NULL) {
|
||||
mp_obj_base_t *o = (mp_obj_base_t*)MP_OBJ_TO_PTR(a);
|
||||
mp_buffer_info_t bufinfo;
|
||||
int ret = o->type->buffer_p.get_buffer(MP_OBJ_FROM_PTR(o), &bufinfo, MP_BUFFER_READ); // TODO: MP_BUFFER_READ?
|
||||
if (ret != 0) {
|
||||
goto __error;
|
||||
}
|
||||
values[i] = (ffi_arg)(intptr_t)bufinfo.buf;
|
||||
} else if (mp_obj_is_type(a, &fficallback_type)) {
|
||||
mp_obj_fficallback_t *p = MP_OBJ_TO_PTR(a);
|
||||
values[i] = (ffi_arg)(intptr_t)p->func;
|
||||
} else {
|
||||
goto __error;
|
||||
}
|
||||
}
|
||||
|
||||
// If ffi_arg is not big enough to hold a double, then we must pass along a
|
||||
// pointer to a memory location of the correct size.
|
||||
// TODO check if this needs to be done for other types which don't fit into
|
||||
// ffi_arg.
|
||||
#if MICROPY_PY_BUILTINS_FLOAT
|
||||
if (sizeof(ffi_arg) == 4 && self->rettype == 'd') {
|
||||
double retval;
|
||||
//TODO add double supported
|
||||
mp_raise_NotImplementedError("The double return type NOT supported");
|
||||
// ffi_call(self->func, &retval, n_args, values);
|
||||
return mp_obj_new_float(retval);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
ffi_arg retval;
|
||||
ffi_call(self->func, &retval, n_args, values);
|
||||
m_free(values);
|
||||
return return_ffi_value((void *)retval, self->rettype);
|
||||
}
|
||||
|
||||
__error:
|
||||
mp_raise_TypeError("Don't know how to pass object to native function");
|
||||
m_free(values);
|
||||
}
|
||||
|
||||
STATIC const mp_obj_type_t ffifunc_type = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_ffifunc,
|
||||
.print = ffifunc_print,
|
||||
.call = ffifunc_call,
|
||||
};
|
||||
|
||||
// FFI callback for Python function
|
||||
|
||||
STATIC void fficallback_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
|
||||
(void)kind;
|
||||
mp_obj_fficallback_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
mp_printf(print, "<fficallback %p>", self->func);
|
||||
}
|
||||
|
||||
STATIC const mp_obj_type_t fficallback_type = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_fficallback,
|
||||
.print = fficallback_print,
|
||||
};
|
||||
|
||||
// FFI variable
|
||||
|
||||
STATIC void ffivar_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
|
||||
(void)kind;
|
||||
mp_obj_ffivar_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
// Variable value printed as cast to int
|
||||
mp_printf(print, "<ffivar @%p: 0x%x>", self->var, *(int*)self->var);
|
||||
}
|
||||
|
||||
STATIC mp_obj_t ffivar_get(mp_obj_t self_in) {
|
||||
mp_obj_ffivar_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
return mp_binary_get_val_array(self->type, self->var, 0);
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(ffivar_get_obj, ffivar_get);
|
||||
|
||||
STATIC mp_obj_t ffivar_set(mp_obj_t self_in, mp_obj_t val_in) {
|
||||
mp_obj_ffivar_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
mp_binary_set_val_array(self->type, self->var, 0, val_in);
|
||||
return mp_const_none;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_2(ffivar_set_obj, ffivar_set);
|
||||
|
||||
STATIC const mp_rom_map_elem_t ffivar_locals_dict_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR_get), MP_ROM_PTR(&ffivar_get_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_set), MP_ROM_PTR(&ffivar_set_obj) },
|
||||
};
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(ffivar_locals_dict, ffivar_locals_dict_table);
|
||||
|
||||
STATIC const mp_obj_type_t ffivar_type = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_ffivar,
|
||||
.print = ffivar_print,
|
||||
.locals_dict = (mp_obj_dict_t*)&ffivar_locals_dict,
|
||||
};
|
||||
|
||||
STATIC mp_obj_t mod_ffi_open(size_t n_args, const mp_obj_t *args) {
|
||||
return ffimod_make_new(&ffimod_type, n_args, 0, args);
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_ffi_open_obj, 1, 2, mod_ffi_open);
|
||||
|
||||
STATIC mp_obj_t mod_ffi_as_bytearray(mp_obj_t ptr, mp_obj_t size) {
|
||||
return mp_obj_new_bytearray_by_ref(mp_obj_int_get_truncated(size), (void*)(uintptr_t)mp_obj_int_get_truncated(ptr));
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_2(mod_ffi_as_bytearray_obj, mod_ffi_as_bytearray);
|
||||
|
||||
STATIC const mp_rom_map_elem_t mp_module_ffi_globals_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_ffi) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_open), MP_ROM_PTR(&mod_ffi_open_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_callback), MP_ROM_PTR(&mod_ffi_callback_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_func), MP_ROM_PTR(&mod_ffi_func_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_as_bytearray), MP_ROM_PTR(&mod_ffi_as_bytearray_obj) },
|
||||
};
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(mp_module_ffi_globals, mp_module_ffi_globals_table);
|
||||
|
||||
const mp_obj_module_t mp_module_ffi = {
|
||||
.base = { &mp_type_module },
|
||||
.globals = (mp_obj_dict_t*)&mp_module_ffi_globals,
|
||||
};
|
||||
|
||||
#endif /* MICROPY_PY_FFI */
|
||||
@@ -0,0 +1,286 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2013, 2014 Damien P. George
|
||||
*
|
||||
* 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 "py/mpconfig.h"
|
||||
|
||||
#if MICROPY_PY_IO
|
||||
|
||||
#include "py/runtime.h"
|
||||
#include "py/stream.h"
|
||||
#include "py/builtin.h"
|
||||
#include "py/mphal.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#define fsync _commit
|
||||
#endif
|
||||
|
||||
typedef struct _mp_obj_fdfile_t {
|
||||
mp_obj_base_t base;
|
||||
int fd;
|
||||
} mp_obj_fdfile_t;
|
||||
|
||||
#ifdef MICROPY_CPYTHON_COMPAT
|
||||
STATIC void check_fd_is_open(const mp_obj_fdfile_t *o) {
|
||||
if (o->fd < 0) {
|
||||
mp_raise_ValueError("I/O operation on closed file");
|
||||
}
|
||||
}
|
||||
#else
|
||||
#define check_fd_is_open(o)
|
||||
#endif
|
||||
|
||||
extern const mp_obj_type_t mp_type_fileio;
|
||||
extern const mp_obj_type_t mp_type_textio;
|
||||
|
||||
STATIC void fdfile_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
|
||||
(void)kind;
|
||||
mp_obj_fdfile_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
mp_printf(print, "<io.%s %d>", mp_obj_get_type_str(self_in), self->fd);
|
||||
}
|
||||
|
||||
STATIC mp_uint_t fdfile_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) {
|
||||
mp_obj_fdfile_t *o = MP_OBJ_TO_PTR(o_in);
|
||||
check_fd_is_open(o);
|
||||
mp_int_t r = read(o->fd, buf, size);
|
||||
if (r == -1) {
|
||||
*errcode = errno;
|
||||
return MP_STREAM_ERROR;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
STATIC mp_uint_t fdfile_write(mp_obj_t o_in, const void *buf, mp_uint_t size, int *errcode) {
|
||||
mp_obj_fdfile_t *o = MP_OBJ_TO_PTR(o_in);
|
||||
check_fd_is_open(o);
|
||||
#if MICROPY_PY_OS_DUPTERM
|
||||
if (o->fd <= STDERR_FILENO) {
|
||||
mp_hal_stdout_tx_strn(buf, size);
|
||||
return size;
|
||||
}
|
||||
#endif
|
||||
mp_int_t r = write(o->fd, buf, size);
|
||||
while (r == -1 && errno == MP_EINTR) {
|
||||
if (MP_STATE_VM(mp_pending_exception) != MP_OBJ_NULL) {
|
||||
mp_obj_t obj = MP_STATE_VM(mp_pending_exception);
|
||||
MP_STATE_VM(mp_pending_exception) = MP_OBJ_NULL;
|
||||
nlr_raise(obj);
|
||||
}
|
||||
r = write(o->fd, buf, size);
|
||||
}
|
||||
if (r == -1) {
|
||||
*errcode = errno;
|
||||
return MP_STREAM_ERROR;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
STATIC mp_uint_t fdfile_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_t arg, int *errcode) {
|
||||
mp_obj_fdfile_t *o = MP_OBJ_TO_PTR(o_in);
|
||||
check_fd_is_open(o);
|
||||
switch (request) {
|
||||
case MP_STREAM_SEEK: {
|
||||
struct mp_stream_seek_t *s = (struct mp_stream_seek_t*)arg;
|
||||
off_t off = lseek(o->fd, s->offset, s->whence);
|
||||
if (off == (off_t)-1) {
|
||||
*errcode = errno;
|
||||
return MP_STREAM_ERROR;
|
||||
}
|
||||
s->offset = off;
|
||||
return 0;
|
||||
}
|
||||
case MP_STREAM_FLUSH:
|
||||
if (fsync(o->fd) < 0) {
|
||||
*errcode = errno;
|
||||
return MP_STREAM_ERROR;
|
||||
}
|
||||
return 0;
|
||||
default:
|
||||
*errcode = EINVAL;
|
||||
return MP_STREAM_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
STATIC mp_obj_t fdfile_close(mp_obj_t self_in) {
|
||||
mp_obj_fdfile_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
close(self->fd);
|
||||
#ifdef MICROPY_CPYTHON_COMPAT
|
||||
self->fd = -1;
|
||||
#endif
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(fdfile_close_obj, fdfile_close);
|
||||
|
||||
STATIC mp_obj_t fdfile___exit__(size_t n_args, const mp_obj_t *args) {
|
||||
(void)n_args;
|
||||
return fdfile_close(args[0]);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(fdfile___exit___obj, 4, 4, fdfile___exit__);
|
||||
|
||||
STATIC mp_obj_t fdfile_fileno(mp_obj_t self_in) {
|
||||
mp_obj_fdfile_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
check_fd_is_open(self);
|
||||
return MP_OBJ_NEW_SMALL_INT(self->fd);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(fdfile_fileno_obj, fdfile_fileno);
|
||||
|
||||
// Note: encoding is ignored for now; it's also not a valid kwarg for CPython's FileIO,
|
||||
// but by adding it here we can use one single mp_arg_t array for open() and FileIO's constructor
|
||||
STATIC const mp_arg_t file_open_args[] = {
|
||||
{ MP_QSTR_file, MP_ARG_OBJ | MP_ARG_REQUIRED, {.u_rom_obj = MP_ROM_NONE} },
|
||||
{ MP_QSTR_mode, MP_ARG_OBJ, {.u_obj = MP_OBJ_NEW_QSTR(MP_QSTR_r)} },
|
||||
{ MP_QSTR_buffering, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} },
|
||||
{ MP_QSTR_encoding, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} },
|
||||
};
|
||||
#define FILE_OPEN_NUM_ARGS MP_ARRAY_SIZE(file_open_args)
|
||||
|
||||
STATIC mp_obj_t fdfile_open(const mp_obj_type_t *type, mp_arg_val_t *args) {
|
||||
mp_obj_fdfile_t *o = m_new_obj(mp_obj_fdfile_t);
|
||||
const char *mode_s = mp_obj_str_get_str(args[1].u_obj);
|
||||
|
||||
int mode_rw = 0, mode_x = 0;
|
||||
while (*mode_s) {
|
||||
switch (*mode_s++) {
|
||||
case 'r':
|
||||
mode_rw = O_RDONLY;
|
||||
break;
|
||||
case 'w':
|
||||
mode_rw = O_WRONLY;
|
||||
mode_x = O_CREAT | O_TRUNC;
|
||||
break;
|
||||
case 'a':
|
||||
mode_rw = O_WRONLY;
|
||||
mode_x = O_CREAT | O_APPEND;
|
||||
break;
|
||||
case '+':
|
||||
mode_rw = O_RDWR;
|
||||
break;
|
||||
#if MICROPY_PY_IO_FILEIO
|
||||
// If we don't have io.FileIO, then files are in text mode implicitly
|
||||
case 'b':
|
||||
type = &mp_type_fileio;
|
||||
break;
|
||||
case 't':
|
||||
type = &mp_type_textio;
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
o->base.type = type;
|
||||
|
||||
mp_obj_t fid = args[0].u_obj;
|
||||
|
||||
if (MP_OBJ_IS_SMALL_INT(fid)) {
|
||||
o->fd = MP_OBJ_SMALL_INT_VALUE(fid);
|
||||
return MP_OBJ_FROM_PTR(o);
|
||||
}
|
||||
|
||||
const char *fname = mp_obj_str_get_str(fid);
|
||||
int fd = open(fname, mode_x | mode_rw, 0644);
|
||||
if (fd == -1) {
|
||||
mp_raise_OSError(errno);
|
||||
}
|
||||
o->fd = fd;
|
||||
return MP_OBJ_FROM_PTR(o);
|
||||
}
|
||||
|
||||
STATIC mp_obj_t fdfile_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
|
||||
mp_arg_val_t arg_vals[FILE_OPEN_NUM_ARGS];
|
||||
mp_arg_parse_all_kw_array(n_args, n_kw, args, FILE_OPEN_NUM_ARGS, file_open_args, arg_vals);
|
||||
return fdfile_open(type, arg_vals);
|
||||
}
|
||||
|
||||
STATIC const mp_rom_map_elem_t rawfile_locals_dict_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR_fileno), MP_ROM_PTR(&fdfile_fileno_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_readlines), MP_ROM_PTR(&mp_stream_unbuffered_readlines_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_seek), MP_ROM_PTR(&mp_stream_seek_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_tell), MP_ROM_PTR(&mp_stream_tell_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_flush), MP_ROM_PTR(&mp_stream_flush_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&fdfile_close_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&mp_identity_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&fdfile___exit___obj) },
|
||||
};
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(rawfile_locals_dict, rawfile_locals_dict_table);
|
||||
|
||||
#if MICROPY_PY_IO_FILEIO
|
||||
STATIC const mp_stream_p_t fileio_stream_p = {
|
||||
.read = fdfile_read,
|
||||
.write = fdfile_write,
|
||||
.ioctl = fdfile_ioctl,
|
||||
};
|
||||
|
||||
const mp_obj_type_t mp_type_fileio = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_FileIO,
|
||||
.print = fdfile_print,
|
||||
.make_new = fdfile_make_new,
|
||||
.getiter = mp_identity_getiter,
|
||||
.iternext = mp_stream_unbuffered_iter,
|
||||
.protocol = &fileio_stream_p,
|
||||
.locals_dict = (mp_obj_dict_t*)&rawfile_locals_dict,
|
||||
};
|
||||
#endif
|
||||
|
||||
STATIC const mp_stream_p_t textio_stream_p = {
|
||||
.read = fdfile_read,
|
||||
.write = fdfile_write,
|
||||
.ioctl = fdfile_ioctl,
|
||||
.is_text = true,
|
||||
};
|
||||
|
||||
const mp_obj_type_t mp_type_textio = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_TextIOWrapper,
|
||||
.print = fdfile_print,
|
||||
.make_new = fdfile_make_new,
|
||||
.getiter = mp_identity_getiter,
|
||||
.iternext = mp_stream_unbuffered_iter,
|
||||
.protocol = &textio_stream_p,
|
||||
.locals_dict = (mp_obj_dict_t*)&rawfile_locals_dict,
|
||||
};
|
||||
|
||||
// Factory function for I/O stream classes
|
||||
mp_obj_t mp_builtin_open(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) {
|
||||
// TODO: analyze buffering args and instantiate appropriate type
|
||||
mp_arg_val_t arg_vals[FILE_OPEN_NUM_ARGS];
|
||||
mp_arg_parse_all(n_args, args, kwargs, FILE_OPEN_NUM_ARGS, file_open_args, arg_vals);
|
||||
return fdfile_open(&mp_type_textio, arg_vals);
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_KW(mp_builtin_open_obj, 1, mp_builtin_open);
|
||||
|
||||
#endif // MICROPY_PY_IO
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2014 Damien P. George
|
||||
*
|
||||
* 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 <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "py/objlist.h"
|
||||
#include "py/runtime.h"
|
||||
#include "py/mphal.h"
|
||||
#include "lib/netutils/netutils.h"
|
||||
#include "modnetwork.h"
|
||||
|
||||
#if MICROPY_PY_NETWORK
|
||||
|
||||
STATIC const mp_rom_map_elem_t mp_module_network_globals_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_network) },
|
||||
|
||||
#if defined(MICROPY_PY_WLAN)
|
||||
{ MP_ROM_QSTR(MP_QSTR_WLAN), MP_ROM_PTR(&get_wlan_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_STA_IF), MP_ROM_INT(STATION_IF)},
|
||||
{ MP_ROM_QSTR(MP_QSTR_AP_IF), MP_ROM_INT(SOFTAP_IF)},
|
||||
#endif
|
||||
};
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(mp_module_network_globals, mp_module_network_globals_table);
|
||||
|
||||
const mp_obj_module_t mp_module_network = {
|
||||
.base = { &mp_type_module },
|
||||
.globals = (mp_obj_dict_t*)&mp_module_network_globals,
|
||||
};
|
||||
|
||||
#endif // MICROPY_PY_NETWORK
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2013, 2014 Damien P. George
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef MICROPY_INCLUDED_MODNETWORK_H
|
||||
#define MICROPY_INCLUDED_MODNETWORK_H
|
||||
|
||||
#define STATION_IF 0
|
||||
#define SOFTAP_IF 1
|
||||
|
||||
#define MOD_NETWORK_AF_INET (2)
|
||||
#define MOD_NETWORK_AF_INET6 (10)
|
||||
|
||||
#define MOD_NETWORK_SOCK_STREAM (1)
|
||||
#define MOD_NETWORK_SOCK_DGRAM (2)
|
||||
#define MOD_NETWORK_SOCK_RAW (3)
|
||||
|
||||
#define MODNETWORK_INCLUDE_CONSTANTS (1)
|
||||
|
||||
MP_DECLARE_CONST_FUN_OBJ_KW(get_wlan_obj);
|
||||
|
||||
#endif // MICROPY_INCLUDED_MODNETWORK_H
|
||||
@@ -0,0 +1,571 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2019 SummerGift <SummerGift@qq.com>
|
||||
*
|
||||
* 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 <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "py/objlist.h"
|
||||
#include "py/runtime.h"
|
||||
#include "py/mphal.h"
|
||||
#include "lib/netutils/netutils.h"
|
||||
|
||||
#if MICROPY_PY_WLAN
|
||||
#include <rtthread.h>
|
||||
#include <wlan_mgnt.h>
|
||||
#include <wlan_cfg.h>
|
||||
#include <wlan_prot.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netdev.h>
|
||||
#include "modnetwork.h"
|
||||
|
||||
extern struct netdev *netdev_default;
|
||||
|
||||
typedef struct _wlan_if_obj_t {
|
||||
mp_obj_base_t base;
|
||||
int if_id;
|
||||
} wlan_if_obj_t;
|
||||
|
||||
enum {
|
||||
STATION_IDLE = 0,
|
||||
STATION_CONNECTING,
|
||||
STATION_WRONG_PASSWORD,
|
||||
STATION_NO_AP_FOUND,
|
||||
STATION_CONNECT_FAIL,
|
||||
STATION_GOT_IP,
|
||||
};
|
||||
|
||||
const mp_obj_type_t wlan_if_type;
|
||||
STATIC struct rt_wlan_info _ap_info;
|
||||
STATIC char _ap_password[RT_WLAN_PASSWORD_MAX_LENGTH];
|
||||
|
||||
STATIC void error_check(bool status, const char *msg) {
|
||||
if (!status) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, msg));
|
||||
}
|
||||
}
|
||||
|
||||
STATIC const wlan_if_obj_t wlan_objs[] = {
|
||||
{{&wlan_if_type}, STATION_IF},
|
||||
{{&wlan_if_type}, SOFTAP_IF},
|
||||
};
|
||||
|
||||
STATIC void require_if(mp_obj_t wlan_if, int if_no) {
|
||||
wlan_if_obj_t *self = MP_OBJ_TO_PTR(wlan_if);
|
||||
if (self->if_id != if_no) {
|
||||
error_check(false, if_no == STATION_IF ? "STA required" : "AP required");
|
||||
}
|
||||
}
|
||||
|
||||
STATIC mp_obj_t get_wlan(size_t n_args, const mp_obj_t *args) {
|
||||
int idx = 0;
|
||||
if (n_args > 0) {
|
||||
idx = mp_obj_get_int(args[0]);
|
||||
if (idx < 0 || idx >= sizeof(wlan_objs)) {
|
||||
mp_raise_ValueError(NULL);
|
||||
}
|
||||
}
|
||||
return MP_OBJ_FROM_PTR(&wlan_objs[idx]);
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(get_wlan_obj, 0, 1, get_wlan);
|
||||
|
||||
STATIC mp_obj_t wlan_active(size_t n_args, const mp_obj_t *args) {
|
||||
|
||||
wlan_if_obj_t *self = MP_OBJ_TO_PTR(args[0]);
|
||||
|
||||
if (n_args > 1) {
|
||||
|
||||
if (self->if_id == STATION_IF)
|
||||
{
|
||||
if (mp_obj_get_int(args[1]) == RT_TRUE)
|
||||
{
|
||||
error_check(netdev_set_up(netdev_default) == RT_EOK, "Cannot active wlan device");
|
||||
}
|
||||
else
|
||||
{
|
||||
error_check(netdev_set_down(netdev_default) == RT_EOK, "Cannot disable wlan device");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mp_obj_get_int(args[1]) == RT_TRUE)
|
||||
{
|
||||
error_check(rt_wlan_start_ap((char *)&_ap_info.ssid.val, _ap_password) == RT_EOK, "Cannot start AP");
|
||||
}
|
||||
else
|
||||
{
|
||||
error_check(rt_wlan_ap_stop() == RT_EOK, "Cannot stop AP");
|
||||
}
|
||||
}
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
if (self->if_id == STATION_IF)
|
||||
{
|
||||
return mp_obj_new_bool(rt_wlan_get_mode("wlan0") == RT_WLAN_STATION);
|
||||
}
|
||||
else
|
||||
{
|
||||
return mp_obj_new_bool(rt_wlan_get_mode("wlan1") == RT_WLAN_AP);
|
||||
}
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(wlan_active_obj, 1, 2, wlan_active);
|
||||
|
||||
STATIC mp_obj_t wlan_connect(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
enum { ARG_ssid, ARG_password, ARG_bssid };
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{ MP_QSTR_, MP_ARG_OBJ, {.u_obj = mp_const_none} },
|
||||
{ MP_QSTR_, MP_ARG_OBJ, {.u_obj = mp_const_none} },
|
||||
{ MP_QSTR_bssid, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
|
||||
};
|
||||
|
||||
// parse args
|
||||
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
|
||||
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
|
||||
|
||||
require_if(pos_args[0], STATION_IF);
|
||||
|
||||
const char *ssid = RT_NULL;
|
||||
const char *key = RT_NULL;
|
||||
size_t len;
|
||||
const char *p;
|
||||
|
||||
// set parameters based on given args
|
||||
if (args[ARG_ssid].u_obj != mp_const_none) {
|
||||
p = mp_obj_str_get_data(args[ARG_ssid].u_obj, &len);
|
||||
ssid = p;
|
||||
}
|
||||
|
||||
if (args[ARG_password].u_obj != mp_const_none) {
|
||||
p = mp_obj_str_get_data(args[ARG_password].u_obj, &len);
|
||||
key = p;
|
||||
}
|
||||
|
||||
error_check(rt_wlan_connect(ssid, key) == RT_EOK, "Cannot connect to AP");
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(wlan_connect_obj, 1, wlan_connect);
|
||||
|
||||
STATIC mp_obj_t wlan_disconnect(mp_obj_t self_in) {
|
||||
require_if(self_in, STATION_IF);
|
||||
error_check(rt_wlan_disconnect() == RT_EOK, "Cannot disconnect from AP");
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(wlan_disconnect_obj, wlan_disconnect);
|
||||
|
||||
STATIC mp_obj_t wlan_status(size_t n_args, const mp_obj_t *args) {
|
||||
wlan_if_obj_t *self = MP_OBJ_TO_PTR(args[0]);
|
||||
if (n_args == 1) {
|
||||
// Get link status
|
||||
if (self->if_id == STATION_IF) {
|
||||
|
||||
if(rt_wlan_is_ready() == RT_EOK)
|
||||
{
|
||||
return MP_OBJ_NEW_SMALL_INT(STATION_GOT_IP);
|
||||
}
|
||||
else
|
||||
{
|
||||
return MP_OBJ_NEW_SMALL_INT(STATION_IDLE);
|
||||
}
|
||||
}
|
||||
return MP_OBJ_NEW_SMALL_INT(-1);
|
||||
} else {
|
||||
// Get specific status parameter
|
||||
switch (mp_obj_str_get_qstr(args[1])) {
|
||||
case MP_QSTR_rssi:
|
||||
if (self->if_id == STATION_IF) {
|
||||
return MP_OBJ_NEW_SMALL_INT(rt_wlan_get_rssi());
|
||||
}
|
||||
}
|
||||
mp_raise_ValueError("unknown status param");
|
||||
}
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(wlan_status_obj, 1, 2, wlan_status);
|
||||
|
||||
STATIC mp_obj_t *wlan_scan_list = NULL;
|
||||
|
||||
void wlan_station_scan(void)
|
||||
{
|
||||
if (wlan_scan_list == NULL) {
|
||||
// called unexpectedly
|
||||
return;
|
||||
}
|
||||
|
||||
struct rt_wlan_scan_result *scan_result = RT_NULL;
|
||||
|
||||
/* scan ap info */
|
||||
scan_result = rt_wlan_scan_sync();
|
||||
if (scan_result)
|
||||
{
|
||||
int index, num;
|
||||
char *security;
|
||||
|
||||
num = scan_result->num;
|
||||
for (index = 0; index < num; index ++)
|
||||
{
|
||||
switch (scan_result->info[index].security)
|
||||
{
|
||||
case SECURITY_OPEN:
|
||||
security = "OPEN";
|
||||
break;
|
||||
case SECURITY_WEP_PSK:
|
||||
security = "WEP_PSK";
|
||||
break;
|
||||
case SECURITY_WEP_SHARED:
|
||||
security = "WEP_SHARED";
|
||||
break;
|
||||
case SECURITY_WPA_TKIP_PSK:
|
||||
security = "WPA_TKIP_PSK";
|
||||
break;
|
||||
case SECURITY_WPA_AES_PSK:
|
||||
security = "WPA_AES_PSK";
|
||||
break;
|
||||
case SECURITY_WPA2_AES_PSK:
|
||||
security = "WPA2_AES_PSK";
|
||||
break;
|
||||
case SECURITY_WPA2_TKIP_PSK:
|
||||
security = "WPA2_TKIP_PSK";
|
||||
break;
|
||||
case SECURITY_WPA2_MIXED_PSK:
|
||||
security = "WPA2_MIXED_PSK";
|
||||
break;
|
||||
case SECURITY_WPS_OPEN:
|
||||
security = "WPS_OPEN";
|
||||
break;
|
||||
case SECURITY_WPS_SECURE:
|
||||
security = "WPS_SECURE";
|
||||
break;
|
||||
default:
|
||||
security = "UNKNOWN";
|
||||
break;
|
||||
}
|
||||
|
||||
mp_obj_tuple_t *t = mp_obj_new_tuple(6, NULL);
|
||||
t->items[0] = mp_obj_new_bytes(&scan_result->info[index].ssid.val[0], strlen((char *)(&scan_result->info[index].ssid.val[0])));
|
||||
t->items[1] = mp_obj_new_bytes(&scan_result->info[index].bssid[0], strlen((char *)(&scan_result->info[index].bssid[0])));
|
||||
t->items[2] = MP_OBJ_NEW_SMALL_INT(scan_result->info[index].channel);
|
||||
t->items[3] = MP_OBJ_NEW_SMALL_INT(scan_result->info[index].rssi);
|
||||
t->items[4] = mp_obj_new_bytes((const byte *)security, strlen(security));
|
||||
t->items[5] = MP_OBJ_NEW_SMALL_INT(scan_result->info[index].hidden);
|
||||
|
||||
mp_obj_list_append(*wlan_scan_list, MP_OBJ_FROM_PTR(t));
|
||||
|
||||
}
|
||||
rt_wlan_scan_result_clean();
|
||||
}
|
||||
else
|
||||
{
|
||||
mp_printf(&mp_plat_print, ("wifi scan result is null\n"));
|
||||
*wlan_scan_list = MP_OBJ_NULL;
|
||||
}
|
||||
}
|
||||
|
||||
STATIC mp_obj_t wlan_scan(mp_obj_t self_in) {
|
||||
require_if(self_in, STATION_IF);
|
||||
|
||||
mp_obj_t list = mp_obj_new_list(0, NULL);
|
||||
wlan_scan_list = &list;
|
||||
wlan_station_scan();
|
||||
|
||||
if (list == MP_OBJ_NULL) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "scan failed"));
|
||||
}
|
||||
return list;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(wlan_scan_obj, wlan_scan);
|
||||
|
||||
/// \method isconnected()
|
||||
/// Return True if connected to an AP and an IP address has been assigned,
|
||||
/// false otherwise.
|
||||
STATIC mp_obj_t wlan_isconnected(mp_obj_t self_in) {
|
||||
wlan_if_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
if (self->if_id == STATION_IF) {
|
||||
if (rt_wlan_is_connected() == RT_TRUE) {
|
||||
return mp_const_true;
|
||||
}
|
||||
} else {
|
||||
if (rt_wlan_ap_get_sta_num() > 0) {
|
||||
return mp_const_true;
|
||||
}
|
||||
}
|
||||
return mp_const_false;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(wlan_isconnected_obj, wlan_isconnected);
|
||||
|
||||
STATIC mp_obj_t wlan_ifconfig(size_t n_args, const mp_obj_t *args) {
|
||||
wlan_if_obj_t *self = MP_OBJ_TO_PTR(args[0]);
|
||||
|
||||
struct netdev *netdev = netdev_default;
|
||||
if (netdev == RT_NULL)
|
||||
{
|
||||
mp_printf(&mp_plat_print, ("not find wlan interface device.\n"));
|
||||
return MP_OBJ_NEW_SMALL_INT(-1);
|
||||
}
|
||||
|
||||
if (n_args == 1) {
|
||||
// get
|
||||
mp_obj_t tuple[4] = {
|
||||
mp_obj_new_str((const char *)inet_ntoa(netdev->ip_addr), strlen((char *)(inet_ntoa(netdev->ip_addr)))),
|
||||
mp_obj_new_str((const char *)inet_ntoa(netdev->netmask), strlen((char *)(inet_ntoa(netdev->netmask)))),
|
||||
mp_obj_new_str((const char *)inet_ntoa(netdev->gw), strlen((char *)(inet_ntoa(netdev->gw)))),
|
||||
mp_obj_new_str((const char *)inet_ntoa(netdev->dns_servers), strlen((char *)(inet_ntoa(netdev->dns_servers)))),
|
||||
};
|
||||
return mp_obj_new_tuple(4, tuple);
|
||||
}
|
||||
else
|
||||
{
|
||||
// set
|
||||
mp_obj_t *items;
|
||||
uint8_t ip_addr[4];
|
||||
uint8_t netmask[4];
|
||||
uint8_t gw[4];
|
||||
uint8_t dns_server[4];
|
||||
|
||||
mp_obj_get_array_fixed_n(args[1], 4, &items);
|
||||
|
||||
netutils_parse_ipv4_addr(items[0], (uint8_t *)ip_addr, NETUTILS_BIG);
|
||||
netutils_parse_ipv4_addr(items[1], (uint8_t *)netmask, NETUTILS_BIG);
|
||||
netutils_parse_ipv4_addr(items[2], (uint8_t *)gw , NETUTILS_BIG);
|
||||
netutils_parse_ipv4_addr(items[3], (uint8_t *)dns_server, NETUTILS_BIG);
|
||||
|
||||
// To set a static IP we have to disable DHCP first
|
||||
if (self->if_id == STATION_IF) {
|
||||
if(netdev_dhcp_enabled(netdev, 0) == RT_EOK)
|
||||
{
|
||||
if (netdev_set_ipaddr(netdev, (const ip_addr_t *)ip_addr) != RT_EOK)
|
||||
{
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "netdev_set_ipaddr() failed"));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "netdev_dhcp_enabled() failed"));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO modify IP netmask gw under AP mode
|
||||
netdev_set_dns_server(netdev, 0, (const ip_addr_t *)dns_server);
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
netdev_set_netmask(netdev, (const ip_addr_t *)netmask);
|
||||
netdev_set_gw(netdev, (const ip_addr_t *)gw);
|
||||
netdev_set_dns_server(netdev, 0, (const ip_addr_t *)dns_server);
|
||||
}
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(wlan_ifconfig_obj, 1, 2, wlan_ifconfig);
|
||||
|
||||
STATIC mp_obj_t wlan_config(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) {
|
||||
if (n_args != 1 && kwargs->used != 0) {
|
||||
mp_raise_TypeError("either pos or kw args are allowed");
|
||||
}
|
||||
|
||||
wlan_if_obj_t *self = MP_OBJ_TO_PTR(args[0]);
|
||||
struct rt_wlan_info cfg = {0};
|
||||
|
||||
if (self->if_id == STATION_IF) {
|
||||
error_check(rt_wlan_get_info(&cfg) == RT_EOK, "can't get STA config");
|
||||
} else {
|
||||
error_check(rt_wlan_ap_get_info(&cfg) == RT_EOK, "can't get AP config");
|
||||
}
|
||||
|
||||
int req_if = -1;
|
||||
|
||||
if (kwargs->used != 0) {
|
||||
|
||||
for (mp_uint_t i = 0; i < kwargs->alloc; i++) {
|
||||
if (mp_map_slot_is_filled(kwargs, i)) {
|
||||
#define QS(x) (uintptr_t)MP_OBJ_NEW_QSTR(x)
|
||||
switch ((uintptr_t)kwargs->table[i].key) {
|
||||
case QS(MP_QSTR_mac): {
|
||||
mp_buffer_info_t bufinfo;
|
||||
mp_get_buffer_raise(kwargs->table[i].value, &bufinfo, MP_BUFFER_READ);
|
||||
if (bufinfo.len != 6) {
|
||||
mp_raise_ValueError("invalid buffer length");
|
||||
}
|
||||
error_check(rt_wlan_set_mac((rt_uint8_t *)bufinfo.buf) == RT_EOK, "can't set MAC");
|
||||
|
||||
break;
|
||||
}
|
||||
case QS(MP_QSTR_essid): {
|
||||
req_if = SOFTAP_IF;
|
||||
size_t len;
|
||||
const char *s = mp_obj_str_get_data(kwargs->table[i].value, &len);
|
||||
len = MIN(len, sizeof(_ap_info.ssid.val));
|
||||
memcpy(_ap_info.ssid.val, s, len);
|
||||
_ap_info.ssid.len = len;
|
||||
break;
|
||||
}
|
||||
case QS(MP_QSTR_hidden): {
|
||||
req_if = SOFTAP_IF;
|
||||
_ap_info.hidden = mp_obj_is_true(kwargs->table[i].value);
|
||||
break;
|
||||
}
|
||||
// case QS(MP_QSTR_authmode): {
|
||||
// req_if = SOFTAP_IF;
|
||||
// cfg.ap.authmode = mp_obj_get_int(kwargs->table[i].value);
|
||||
// break;
|
||||
// }
|
||||
case QS(MP_QSTR_password): {
|
||||
req_if = SOFTAP_IF;
|
||||
size_t len;
|
||||
const char *s = mp_obj_str_get_data(kwargs->table[i].value, &len);
|
||||
len = MIN(len, sizeof(_ap_password) - 1);
|
||||
memcpy(_ap_password, s, len);
|
||||
_ap_password[len] = 0;
|
||||
break;
|
||||
}
|
||||
case QS(MP_QSTR_channel): {
|
||||
req_if = SOFTAP_IF;
|
||||
_ap_info.channel = mp_obj_get_int(kwargs->table[i].value);
|
||||
break;
|
||||
}
|
||||
// case QS(MP_QSTR_dhcp_hostname): {
|
||||
// req_if = STATION_IF;
|
||||
// if (self->if_id == STATION_IF) {
|
||||
// const char *s = mp_obj_str_get_str(kwargs->table[i].value);
|
||||
// wifi_station_set_hostname((char*)s);
|
||||
// }
|
||||
// break;
|
||||
// }
|
||||
default:
|
||||
goto unknown;
|
||||
}
|
||||
#undef QS
|
||||
}
|
||||
}
|
||||
|
||||
// We post-check interface requirements to save on code size
|
||||
if (req_if >= 0) {
|
||||
require_if(args[0], req_if);
|
||||
}
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
// Get config
|
||||
if (n_args != 2) {
|
||||
mp_raise_TypeError("can query only one param");
|
||||
}
|
||||
|
||||
mp_obj_t val;
|
||||
|
||||
qstr key = mp_obj_str_get_qstr(args[1]);
|
||||
switch (key) {
|
||||
case MP_QSTR_mac: {
|
||||
uint8_t mac[6];
|
||||
error_check(rt_wlan_get_mac(mac) == RT_EOK, "can't get mac config");
|
||||
return mp_obj_new_bytes(mac, sizeof(mac));
|
||||
}
|
||||
case MP_QSTR_essid:
|
||||
if (self->if_id == STATION_IF) {
|
||||
val = mp_obj_new_str((char*)cfg.ssid.val, strlen((char*)cfg.ssid.val));
|
||||
} else {
|
||||
val = mp_obj_new_str((char*)_ap_info.ssid.val, _ap_info.ssid.len);
|
||||
}
|
||||
break;
|
||||
case MP_QSTR_hidden:
|
||||
req_if = SOFTAP_IF;
|
||||
val = mp_obj_new_bool(cfg.hidden);
|
||||
break;
|
||||
// case MP_QSTR_authmode:
|
||||
// req_if = SOFTAP_IF;
|
||||
// val = MP_OBJ_NEW_SMALL_INT(cfg.ap.authmode);
|
||||
// break;
|
||||
case MP_QSTR_channel:
|
||||
req_if = SOFTAP_IF;
|
||||
val = MP_OBJ_NEW_SMALL_INT(cfg.channel);
|
||||
break;
|
||||
// case MP_QSTR_dhcp_hostname: {
|
||||
// req_if = STATION_IF;
|
||||
// char* s = wifi_station_get_hostname();
|
||||
// if (s == NULL) {
|
||||
// val = MP_OBJ_NEW_QSTR(MP_QSTR_);
|
||||
// } else {
|
||||
// val = mp_obj_new_str(s, strlen(s));
|
||||
// }
|
||||
// break;
|
||||
// }
|
||||
default:
|
||||
goto unknown;
|
||||
}
|
||||
|
||||
// We post-check interface requirements to save on code size
|
||||
if (req_if >= 0) {
|
||||
require_if(args[0], req_if);
|
||||
}
|
||||
|
||||
return val;
|
||||
|
||||
unknown:
|
||||
mp_raise_ValueError("unknown config param");
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(wlan_config_obj, 1, wlan_config);
|
||||
|
||||
STATIC const mp_rom_map_elem_t wlan_if_locals_dict_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR_active), MP_ROM_PTR(&wlan_active_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_connect), MP_ROM_PTR(&wlan_connect_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_disconnect), MP_ROM_PTR(&wlan_disconnect_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_status), MP_ROM_PTR(&wlan_status_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_scan), MP_ROM_PTR(&wlan_scan_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_isconnected), MP_ROM_PTR(&wlan_isconnected_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_config), MP_ROM_PTR(&wlan_config_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_ifconfig), MP_ROM_PTR(&wlan_ifconfig_obj) },
|
||||
|
||||
#if MODNETWORK_INCLUDE_CONSTANTS
|
||||
{ MP_ROM_QSTR(MP_QSTR_STAT_IDLE), MP_ROM_INT(STATION_IDLE)},
|
||||
{ MP_ROM_QSTR(MP_QSTR_STAT_CONNECTING), MP_ROM_INT(STATION_CONNECTING)},
|
||||
{ MP_ROM_QSTR(MP_QSTR_STAT_WRONG_PASSWORD), MP_ROM_INT(STATION_WRONG_PASSWORD)},
|
||||
{ MP_ROM_QSTR(MP_QSTR_STAT_NO_AP_FOUND), MP_ROM_INT(STATION_NO_AP_FOUND)},
|
||||
{ MP_ROM_QSTR(MP_QSTR_STAT_CONNECT_FAIL), MP_ROM_INT(STATION_CONNECT_FAIL)},
|
||||
{ MP_ROM_QSTR(MP_QSTR_STAT_GOT_IP), MP_ROM_INT(STATION_GOT_IP)},
|
||||
|
||||
// { MP_ROM_QSTR(MP_QSTR_MODE_11B), MP_ROM_INT(PHY_MODE_11B) },
|
||||
// { MP_ROM_QSTR(MP_QSTR_MODE_11G), MP_ROM_INT(PHY_MODE_11G) },
|
||||
// { MP_ROM_QSTR(MP_QSTR_MODE_11N), MP_ROM_INT(PHY_MODE_11N) },
|
||||
|
||||
// { MP_ROM_QSTR(MP_QSTR_AUTH_OPEN), MP_ROM_INT(AUTH_OPEN) },
|
||||
// { MP_ROM_QSTR(MP_QSTR_AUTH_WEP), MP_ROM_INT(AUTH_WEP) },
|
||||
// { MP_ROM_QSTR(MP_QSTR_AUTH_WPA_PSK), MP_ROM_INT(AUTH_WPA_PSK) },
|
||||
// { MP_ROM_QSTR(MP_QSTR_AUTH_WPA2_PSK), MP_ROM_INT(AUTH_WPA2_PSK) },
|
||||
// { MP_ROM_QSTR(MP_QSTR_AUTH_WPA_WPA2_PSK), MP_ROM_INT(AUTH_WPA_WPA2_PSK) },
|
||||
#endif
|
||||
};
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(wlan_if_locals_dict, wlan_if_locals_dict_table);
|
||||
|
||||
const mp_obj_type_t wlan_if_type = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_WLAN,
|
||||
.locals_dict = (mp_obj_dict_t*)&wlan_if_locals_dict,
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,168 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Armink (armink.ztl@gmail.com)
|
||||
*
|
||||
* 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 <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "py/runtime.h"
|
||||
#include "py/gc.h"
|
||||
#include "py/builtin.h"
|
||||
#include "py/mphal.h"
|
||||
#include "lib/utils/pyexec.h"
|
||||
#include "modmachine.h"
|
||||
#include "extmod/vfs.h"
|
||||
#include "extmod/utime_mphal.h"
|
||||
|
||||
/// \function elapsed_millis(start)
|
||||
/// Returns the number of milliseconds which have elapsed since `start`.
|
||||
///
|
||||
/// This function takes care of counter wrap, and always returns a positive
|
||||
/// number. This means it can be used to measure periods upto about 12.4 days.
|
||||
///
|
||||
/// Example:
|
||||
/// start = pyb.millis()
|
||||
/// while pyb.elapsed_millis(start) < 1000:
|
||||
/// # Perform some operation
|
||||
STATIC mp_obj_t pyb_elapsed_millis(mp_obj_t start) {
|
||||
uint32_t startMillis = mp_obj_get_int(start);
|
||||
uint32_t currMillis = mp_hal_ticks_ms();
|
||||
return MP_OBJ_NEW_SMALL_INT((currMillis - startMillis) & 0x3fffffff);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_elapsed_millis_obj, pyb_elapsed_millis);
|
||||
|
||||
/// \function elapsed_micros(start)
|
||||
/// Returns the number of microseconds which have elapsed since `start`.
|
||||
///
|
||||
/// This function takes care of counter wrap, and always returns a positive
|
||||
/// number. This means it can be used to measure periods upto about 17.8 minutes.
|
||||
///
|
||||
/// Example:
|
||||
/// start = pyb.micros()
|
||||
/// while pyb.elapsed_micros(start) < 1000:
|
||||
/// # Perform some operation
|
||||
STATIC mp_obj_t pyb_elapsed_micros(mp_obj_t start) {
|
||||
uint32_t startMicros = mp_obj_get_int(start);
|
||||
uint32_t currMicros = mp_hal_ticks_us();
|
||||
return MP_OBJ_NEW_SMALL_INT((currMicros - startMicros) & 0x3fffffff);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_elapsed_micros_obj, pyb_elapsed_micros);
|
||||
|
||||
MP_DECLARE_CONST_FUN_OBJ_KW(pyb_main_obj); // defined in main.c
|
||||
|
||||
STATIC const mp_rom_map_elem_t pyb_module_globals_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_pyb) },
|
||||
|
||||
{ MP_ROM_QSTR(MP_QSTR_hard_reset), MP_ROM_PTR(&machine_reset_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_info), MP_ROM_PTR(&machine_info_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_unique_id), MP_ROM_PTR(&machine_unique_id_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_freq), MP_ROM_PTR(&machine_freq_obj) },
|
||||
#if MICROPY_REPL_INFO
|
||||
{ MP_ROM_QSTR(MP_QSTR_repl_info), MP_ROM_PTR(&pyb_set_repl_info_obj) },
|
||||
#endif
|
||||
|
||||
{ MP_ROM_QSTR(MP_QSTR_wfi), MP_ROM_PTR(&pyb_wfi_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_disable_irq), MP_ROM_PTR(&pyb_disable_irq_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_enable_irq), MP_ROM_PTR(&pyb_enable_irq_obj) },
|
||||
|
||||
{ MP_ROM_QSTR(MP_QSTR_stop), MP_ROM_PTR(&machine_sleep_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_standby), MP_ROM_PTR(&machine_deepsleep_obj) },
|
||||
// { MP_ROM_QSTR(MP_QSTR_main), MP_ROM_PTR(&pyb_main_obj) },
|
||||
// { MP_ROM_QSTR(MP_QSTR_repl_uart), MP_ROM_PTR(&pyb_repl_uart_obj) },
|
||||
|
||||
{ MP_ROM_QSTR(MP_QSTR_millis), MP_ROM_PTR(&mp_utime_ticks_ms_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_elapsed_millis), MP_ROM_PTR(&pyb_elapsed_millis_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_micros), MP_ROM_PTR(&mp_utime_ticks_us_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_elapsed_micros), MP_ROM_PTR(&pyb_elapsed_micros_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_delay), MP_ROM_PTR(&mp_utime_sleep_ms_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_udelay), MP_ROM_PTR(&mp_utime_sleep_us_obj) },
|
||||
// { MP_ROM_QSTR(MP_QSTR_mount), MP_ROM_PTR(&mp_os_mount_obj) },
|
||||
|
||||
// { MP_ROM_QSTR(MP_QSTR_Timer), MP_ROM_PTR(&pyb_timer_type) },
|
||||
|
||||
//#if MICROPY_HW_ENABLE_RNG
|
||||
// { MP_ROM_QSTR(MP_QSTR_rng), MP_ROM_PTR(&pyb_rng_get_obj) },
|
||||
//#endif
|
||||
//
|
||||
//#if MICROPY_HW_ENABLE_RTC
|
||||
// { MP_ROM_QSTR(MP_QSTR_RTC), MP_ROM_PTR(&pyb_rtc_type) },
|
||||
//#endif
|
||||
//
|
||||
#if MICROPY_PY_PIN
|
||||
{ MP_ROM_QSTR(MP_QSTR_Pin), MP_ROM_PTR(&machine_pin_type) },
|
||||
#endif
|
||||
// { MP_ROM_QSTR(MP_QSTR_ExtInt), MP_ROM_PTR(&extint_type) },
|
||||
//
|
||||
//#if MICROPY_HW_ENABLE_SERVO
|
||||
// { MP_ROM_QSTR(MP_QSTR_pwm), MP_ROM_PTR(&pyb_pwm_set_obj) },
|
||||
// { MP_ROM_QSTR(MP_QSTR_servo), MP_ROM_PTR(&pyb_servo_set_obj) },
|
||||
// { MP_ROM_QSTR(MP_QSTR_Servo), MP_ROM_PTR(&pyb_servo_type) },
|
||||
//#endif
|
||||
//
|
||||
//#if MICROPY_HW_HAS_SWITCH
|
||||
// { MP_ROM_QSTR(MP_QSTR_Switch), MP_ROM_PTR(&pyb_switch_type) },
|
||||
//#endif
|
||||
//
|
||||
//#if MICROPY_HW_HAS_FLASH
|
||||
// { MP_ROM_QSTR(MP_QSTR_Flash), MP_ROM_PTR(&pyb_flash_type) },
|
||||
//#endif
|
||||
//
|
||||
//#if MICROPY_HW_HAS_SDCARD
|
||||
// { MP_ROM_QSTR(MP_QSTR_SD), MP_ROM_PTR(&pyb_sdcard_obj) }, // now obsolete
|
||||
// { MP_ROM_QSTR(MP_QSTR_SDCard), MP_ROM_PTR(&pyb_sdcard_type) },
|
||||
//#endif
|
||||
//
|
||||
//#if defined(MICROPY_HW_LED1)
|
||||
// { MP_ROM_QSTR(MP_QSTR_LED), MP_ROM_PTR(&pyb_led_type) },
|
||||
//#endif
|
||||
// { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&pyb_i2c_type) },
|
||||
// { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&pyb_spi_type) },
|
||||
// { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&pyb_uart_type) },
|
||||
//#if MICROPY_HW_ENABLE_CAN
|
||||
// { MP_ROM_QSTR(MP_QSTR_CAN), MP_ROM_PTR(&pyb_can_type) },
|
||||
//#endif
|
||||
//
|
||||
// { MP_ROM_QSTR(MP_QSTR_ADC), MP_ROM_PTR(&pyb_adc_type) },
|
||||
// { MP_ROM_QSTR(MP_QSTR_ADCAll), MP_ROM_PTR(&pyb_adc_all_type) },
|
||||
//
|
||||
//#if MICROPY_HW_ENABLE_DAC
|
||||
// { MP_ROM_QSTR(MP_QSTR_DAC), MP_ROM_PTR(&pyb_dac_type) },
|
||||
//#endif
|
||||
//
|
||||
//#if MICROPY_HW_HAS_MMA7660
|
||||
// { MP_ROM_QSTR(MP_QSTR_Accel), MP_ROM_PTR(&pyb_accel_type) },
|
||||
//#endif
|
||||
//
|
||||
//#if MICROPY_HW_HAS_LCD
|
||||
// { MP_ROM_QSTR(MP_QSTR_LCD), MP_ROM_PTR(&pyb_lcd_type) },
|
||||
//#endif
|
||||
};
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(pyb_module_globals, pyb_module_globals_table);
|
||||
|
||||
const mp_obj_module_t pyb_module = {
|
||||
.base = { &mp_type_module },
|
||||
.globals = (mp_obj_dict_t*)&pyb_module_globals,
|
||||
};
|
||||
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Armink (armink.ztl@gmail.com)
|
||||
*
|
||||
* 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 "py/mpconfig.h"
|
||||
#if MICROPY_PY_RTTHREAD
|
||||
|
||||
#include <rtthread.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "py/runtime.h"
|
||||
|
||||
rt_bool_t rt_is_preempt_thread(void) {
|
||||
if (rt_interrupt_get_nest() || rt_critical_level()) {
|
||||
return RT_FALSE;
|
||||
} else {
|
||||
return RT_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
STATIC mp_obj_t mod_is_preempt_thread(void) {
|
||||
return mp_obj_new_bool(rt_is_preempt_thread());
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_is_preempt_thread_obj, mod_is_preempt_thread);
|
||||
|
||||
STATIC mp_obj_t mod_current_tid(void) {
|
||||
return MP_OBJ_NEW_SMALL_INT(rt_thread_self());
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_current_tid_obj, mod_current_tid);
|
||||
|
||||
STATIC mp_obj_t mod_stacks_analyze(void) {
|
||||
#ifdef RT_USING_FINSH
|
||||
extern long list_thread(void);
|
||||
list_thread();
|
||||
#else
|
||||
mp_printf(&mp_plat_print, "Not available when FINSH module disable\n");
|
||||
#endif
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_stacks_analyze_obj, mod_stacks_analyze);
|
||||
|
||||
STATIC mp_obj_t mod_list_device(void) {
|
||||
struct rt_device *device;
|
||||
struct rt_list_node *node;
|
||||
|
||||
struct rt_object_information *info = rt_object_get_information(RT_Object_Class_Device);
|
||||
struct rt_list_node *list = &info->object_list;
|
||||
mp_obj_t mp_list = mp_obj_new_list(0, NULL);
|
||||
|
||||
rt_enter_critical();
|
||||
|
||||
for (node = list->next; node != list; node = node->next)
|
||||
{
|
||||
device = (struct rt_device *)(rt_list_entry(node, struct rt_object, list));
|
||||
|
||||
mp_obj_tuple_t *t = mp_obj_new_tuple(2, NULL);
|
||||
t->items[0] = mp_obj_new_str(device->parent.name, strlen((char *)device->parent.name));
|
||||
t->items[1] = MP_OBJ_NEW_SMALL_INT((device->type <= RT_Device_Class_Unknown) ? device->type : RT_Device_Class_Unknown);
|
||||
mp_obj_list_append(mp_list, MP_OBJ_FROM_PTR(t));
|
||||
}
|
||||
|
||||
rt_exit_critical();
|
||||
|
||||
return mp_list;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_list_device_obj, mod_list_device);
|
||||
|
||||
STATIC const mp_rom_map_elem_t mp_module_rtthread_globals_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_rtthread) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_is_preempt_thread), MP_ROM_PTR(&mod_is_preempt_thread_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_current_tid), MP_ROM_PTR(&mod_current_tid_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_stacks_analyze), MP_ROM_PTR(&mod_stacks_analyze_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_list_device), MP_ROM_PTR(&mod_list_device_obj) },
|
||||
};
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(mp_module_rtthread_globals, mp_module_rtthread_globals_table);
|
||||
|
||||
const mp_obj_module_t mp_module_rtthread = {
|
||||
.base = { &mp_type_module },
|
||||
.globals = (mp_obj_dict_t*)&mp_module_rtthread_globals,
|
||||
};
|
||||
|
||||
#endif // MICROPY_PY_RTTHREAD
|
||||
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 SummerGift <zhangyuan@rt-thread.com>
|
||||
*
|
||||
* 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 "py/mpconfig.h"
|
||||
|
||||
#if MICROPY_PY_MODUOS
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "py/runtime.h"
|
||||
#include "py/objtuple.h"
|
||||
#include "py/objstr.h"
|
||||
#include "py/mperrno.h"
|
||||
#include "lib/timeutils/timeutils.h"
|
||||
#include "extmod/misc.h"
|
||||
#include "genhdr/mpversion.h"
|
||||
|
||||
#if !MICROPY_VFS
|
||||
#if MICROPY_PY_MODUOS_FILE
|
||||
#include "moduos_file.h"
|
||||
#endif
|
||||
#else
|
||||
#include "extmod/vfs.h"
|
||||
#if MICROPY_VFS_FAT
|
||||
#include "extmod/vfs_fat.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
STATIC const qstr os_uname_info_fields[] = {
|
||||
MP_QSTR_sysname, MP_QSTR_nodename,
|
||||
MP_QSTR_release, MP_QSTR_version, MP_QSTR_machine
|
||||
};
|
||||
STATIC const MP_DEFINE_STR_OBJ(os_uname_info_sysname_obj, "pyboard");
|
||||
STATIC const MP_DEFINE_STR_OBJ(os_uname_info_nodename_obj, "pyboard");
|
||||
STATIC const MP_DEFINE_STR_OBJ(os_uname_info_release_obj, MICROPY_VERSION_STRING);
|
||||
STATIC const MP_DEFINE_STR_OBJ(os_uname_info_version_obj, MICROPY_GIT_TAG " on " MICROPY_BUILD_DATE);
|
||||
STATIC const MP_DEFINE_STR_OBJ(os_uname_info_machine_obj, MICROPY_HW_BOARD_NAME " with " MICROPY_HW_MCU_NAME);
|
||||
STATIC MP_DEFINE_ATTRTUPLE(
|
||||
os_uname_info_obj,
|
||||
os_uname_info_fields,
|
||||
5,
|
||||
(mp_obj_t)&os_uname_info_sysname_obj,
|
||||
(mp_obj_t)&os_uname_info_nodename_obj,
|
||||
(mp_obj_t)&os_uname_info_release_obj,
|
||||
(mp_obj_t)&os_uname_info_version_obj,
|
||||
(mp_obj_t)&os_uname_info_machine_obj
|
||||
);
|
||||
|
||||
STATIC mp_obj_t os_uname(void) {
|
||||
return (mp_obj_t)&os_uname_info_obj;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(os_uname_obj, os_uname);
|
||||
|
||||
STATIC mp_obj_t os_sync(void) {
|
||||
return mp_const_none;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_0(mod_os_sync_obj, os_sync);
|
||||
|
||||
#if MICROPY_HW_ENABLE_RNG
|
||||
/// \function urandom(n)
|
||||
/// Return a bytes object with n random bytes, generated by the hardware
|
||||
/// random number generator.
|
||||
STATIC mp_obj_t os_urandom(mp_obj_t num) {
|
||||
mp_int_t n = mp_obj_get_int(num);
|
||||
vstr_t vstr;
|
||||
vstr_init_len(&vstr, n);
|
||||
for (int i = 0; i < n; i++) {
|
||||
vstr.buf[i] = rng_get();
|
||||
}
|
||||
return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(os_urandom_obj, os_urandom);
|
||||
#endif
|
||||
|
||||
STATIC const mp_rom_map_elem_t os_module_globals_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uos) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_uname), MP_ROM_PTR(&os_uname_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_chdir), MP_ROM_PTR(&mp_posix_chdir_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_getcwd), MP_ROM_PTR(&mp_posix_getcwd_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_listdir), MP_ROM_PTR(&mp_posix_listdir_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_ilistdir), MP_ROM_PTR(&mp_posix_listdir_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_mkdir), MP_ROM_PTR(&mp_posix_mkdir_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_remove), MP_ROM_PTR(&mp_posix_remove_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_rename),MP_ROM_PTR(&mp_posix_rename_obj)},
|
||||
{ MP_ROM_QSTR(MP_QSTR_rmdir), MP_ROM_PTR(&mp_posix_rmdir_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_stat), MP_ROM_PTR(&mp_posix_stat_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_unlink), MP_ROM_PTR(&mp_posix_remove_obj) }, // unlink aliases to remove
|
||||
{ MP_ROM_QSTR(MP_QSTR_sync), MP_ROM_PTR(&mod_os_sync_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_file_crc32), MP_ROM_PTR(&mp_posix_file_crc32_obj) },
|
||||
|
||||
/// \constant sep - separation character used in paths
|
||||
//{ MP_ROM_QSTR(MP_QSTR_sep), MP_ROM_QSTR(MP_QSTR__slash_) },
|
||||
|
||||
#if MICROPY_HW_ENABLE_RNG
|
||||
{ MP_ROM_QSTR(MP_QSTR_urandom), MP_ROM_PTR(&os_urandom_obj) },
|
||||
#endif
|
||||
|
||||
// these are MicroPython extensions
|
||||
{ MP_ROM_QSTR(MP_QSTR_dupterm), MP_ROM_PTR(&mp_uos_dupterm_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_mount), MP_ROM_PTR(&mp_posix_mount_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_umount), MP_ROM_PTR(&mp_posix_umount_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_mkfs), MP_ROM_PTR(&mp_posix_mkfs_obj) },
|
||||
//{ MP_ROM_QSTR(MP_QSTR_VfsFat), MP_ROM_PTR(&mp_fat_vfs_type) },
|
||||
};
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(os_module_globals, os_module_globals_table);
|
||||
|
||||
const mp_obj_module_t mp_module_uos = {
|
||||
.base = { &mp_type_module },
|
||||
.globals = (mp_obj_dict_t*)&os_module_globals,
|
||||
};
|
||||
|
||||
#endif /* MICROPY_PY_MODUOS */
|
||||
@@ -0,0 +1,318 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 SummerGift <zhangyuan@rt-thread.com>
|
||||
*
|
||||
* 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 "py/mpconfig.h"
|
||||
|
||||
#if MICROPY_PY_MODUOS_FILE
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <dfs_posix.h>
|
||||
#include "py/runtime.h"
|
||||
#include "py/objstr.h"
|
||||
#include "py/mperrno.h"
|
||||
#include "moduos_file.h"
|
||||
|
||||
mp_obj_t mp_posix_mount(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_KW(mp_posix_mount_obj, 2, mp_posix_mount);
|
||||
|
||||
mp_obj_t mp_posix_umount(mp_obj_t mnt_in) {
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(mp_posix_umount_obj, mp_posix_umount);
|
||||
|
||||
mp_obj_t mp_posix_mkfs(size_t n_args, const mp_obj_t *args) {
|
||||
|
||||
int result = RT_EOK;
|
||||
char *type = "elm"; /* use the default file system type as 'fatfs' */
|
||||
|
||||
if (n_args == 1)
|
||||
{
|
||||
result = dfs_mkfs(type, mp_obj_str_get_str(args[0]));
|
||||
}else if (n_args == 2)
|
||||
{
|
||||
type = (char *)mp_obj_str_get_str(args[0]);
|
||||
result = dfs_mkfs(type, mp_obj_str_get_str(args[1]));
|
||||
}
|
||||
|
||||
if (result != RT_EOK)
|
||||
{
|
||||
mp_raise_ValueError("mkfs failed, please check filesystem type and device name.");
|
||||
}
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_posix_mkfs_obj, 1, 2, mp_posix_mkfs);
|
||||
|
||||
mp_obj_t mp_posix_chdir(mp_obj_t path_in) {
|
||||
const char *changepath = mp_obj_str_get_str(path_in);
|
||||
if (chdir(changepath) != 0) {
|
||||
mp_printf(&mp_plat_print, "No such directory: %s\n", changepath);
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(mp_posix_chdir_obj, mp_posix_chdir);
|
||||
|
||||
mp_obj_t mp_posix_getcwd(void) {
|
||||
char buf[MICROPY_ALLOC_PATH_MAX + 1];
|
||||
getcwd(buf, sizeof(buf));
|
||||
return mp_obj_new_str(buf, strlen(buf));
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_0(mp_posix_getcwd_obj, mp_posix_getcwd);
|
||||
|
||||
#include <dfs_file.h>
|
||||
static struct dfs_fd fd;
|
||||
static struct dirent dirent;
|
||||
mp_obj_t mp_posix_listdir(size_t n_args, const mp_obj_t *args) {
|
||||
|
||||
mp_obj_t dir_list = mp_obj_new_list(0, NULL);
|
||||
|
||||
struct stat stat;
|
||||
int length;
|
||||
char *fullpath, *path;
|
||||
const char *pathname;
|
||||
|
||||
if (n_args == 0) {
|
||||
#ifdef DFS_USING_WORKDIR
|
||||
extern char working_directory[];
|
||||
pathname = working_directory;
|
||||
#else
|
||||
pathname = "/";
|
||||
#endif
|
||||
} else {
|
||||
pathname = mp_obj_str_get_str(args[0]);
|
||||
}
|
||||
|
||||
fullpath = NULL;
|
||||
if (pathname == NULL)
|
||||
{
|
||||
#ifdef DFS_USING_WORKDIR
|
||||
extern char working_directory[];
|
||||
/* open current working directory */
|
||||
path = rt_strdup(working_directory);
|
||||
#else
|
||||
path = rt_strdup("/");
|
||||
#endif
|
||||
if (path == NULL)
|
||||
mp_raise_OSError(MP_ENOMEM); /* out of memory */
|
||||
}
|
||||
else
|
||||
{
|
||||
path = (char *)pathname;
|
||||
}
|
||||
|
||||
/* list directory */
|
||||
if (dfs_file_open(&fd, path, O_DIRECTORY) == 0)
|
||||
{
|
||||
do {
|
||||
memset(&dirent, 0, sizeof(struct dirent));
|
||||
length = dfs_file_getdents(&fd, &dirent, sizeof(struct dirent));
|
||||
if (length > 0) {
|
||||
memset(&stat, 0, sizeof(struct stat));
|
||||
|
||||
/* build full path for each file */
|
||||
fullpath = dfs_normalize_path(path, dirent.d_name);
|
||||
if (fullpath == NULL)
|
||||
break;
|
||||
|
||||
if (dfs_file_stat(fullpath, &stat) == 0) {
|
||||
mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(3, NULL));
|
||||
t->items[0] = mp_obj_new_str(dirent.d_name, strlen(dirent.d_name));
|
||||
t->items[1] = MP_OBJ_NEW_SMALL_INT(MP_S_IFDIR);
|
||||
t->items[2] = MP_OBJ_NEW_SMALL_INT(0); // no inode number
|
||||
mp_obj_t next = MP_OBJ_FROM_PTR(t);
|
||||
mp_obj_t *items;
|
||||
mp_obj_get_array_fixed_n(next, 3, &items);
|
||||
mp_obj_list_append(dir_list, items[0]);
|
||||
} else {
|
||||
mp_printf(&mp_plat_print, "BAD file: %s\n", dirent.d_name);
|
||||
}
|
||||
rt_free(fullpath);
|
||||
}
|
||||
} while (length > 0);
|
||||
|
||||
dfs_file_close(&fd);
|
||||
}
|
||||
else
|
||||
{
|
||||
// mp_printf(&mp_plat_print, "No such directory\n");
|
||||
}
|
||||
if (pathname == NULL)
|
||||
rt_free(path);
|
||||
|
||||
return dir_list;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_posix_listdir_obj, 0, 1, mp_posix_listdir);
|
||||
|
||||
mp_obj_t mp_posix_mkdir(mp_obj_t path_in) {
|
||||
const char *createpath = mp_obj_str_get_str(path_in);
|
||||
int res = mkdir(createpath, 0);
|
||||
if (res != 0) {
|
||||
mp_raise_OSError(MP_EEXIST);
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(mp_posix_mkdir_obj, mp_posix_mkdir);
|
||||
|
||||
mp_obj_t mp_posix_remove(uint n_args, const mp_obj_t *arg) {
|
||||
int index;
|
||||
if (n_args == 0) {
|
||||
mp_printf(&mp_plat_print, "Usage: rm FILE...\n");
|
||||
mp_printf(&mp_plat_print, "Remove (unlink) the FILE(s).\n");
|
||||
return mp_const_none;
|
||||
}
|
||||
for (index = 0; index < n_args; index++) {
|
||||
//mp_printf(&mp_plat_print, "Remove %s.\n", mp_obj_str_get_str(arg[index]));
|
||||
unlink(mp_obj_str_get_str(arg[index]));
|
||||
}
|
||||
// TODO recursive deletion
|
||||
return mp_const_none;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_VAR(mp_posix_remove_obj, 0, mp_posix_remove);
|
||||
|
||||
mp_obj_t mp_posix_rename(mp_obj_t old_path_in, mp_obj_t new_path_in) {
|
||||
const char *old_path = mp_obj_str_get_str(old_path_in);
|
||||
const char *new_path = mp_obj_str_get_str(new_path_in);
|
||||
int res = rename(old_path, new_path);
|
||||
if (res != 0) {
|
||||
mp_raise_OSError(MP_EPERM);
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_2(mp_posix_rename_obj, mp_posix_rename);
|
||||
|
||||
mp_obj_t mp_posix_rmdir(uint n_args, const mp_obj_t *arg) {
|
||||
int index;
|
||||
if (n_args == 0) {
|
||||
mp_printf(&mp_plat_print, "Usage: rm FILE...\n");
|
||||
mp_printf(&mp_plat_print, "Remove (unlink) the FILE(s).\n");
|
||||
return mp_const_none;
|
||||
}
|
||||
for (index = 0; index < n_args; index++) {
|
||||
//mp_printf(&mp_plat_print, "Remove %s.\n", mp_obj_str_get_str(arg[index]));
|
||||
rmdir(mp_obj_str_get_str(arg[index]));
|
||||
}
|
||||
// TODO recursive deletion
|
||||
return mp_const_none;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_VAR(mp_posix_rmdir_obj, 0, mp_posix_rmdir);
|
||||
|
||||
mp_obj_t mp_posix_stat(mp_obj_t path_in) {
|
||||
struct stat buf;
|
||||
const char *createpath = mp_obj_str_get_str(path_in);
|
||||
int res = stat(createpath, &buf);
|
||||
if (res != 0) {
|
||||
mp_raise_OSError(MP_EPERM);
|
||||
}
|
||||
mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(10, NULL));
|
||||
t->items[0] = MP_OBJ_NEW_SMALL_INT(buf.st_mode); // st_mode
|
||||
t->items[1] = MP_OBJ_NEW_SMALL_INT(buf.st_ino); // st_ino
|
||||
t->items[2] = MP_OBJ_NEW_SMALL_INT(buf.st_dev); // st_dev
|
||||
t->items[3] = MP_OBJ_NEW_SMALL_INT(buf.st_nlink); // st_nlink
|
||||
t->items[4] = MP_OBJ_NEW_SMALL_INT(buf.st_uid); // st_uid
|
||||
t->items[5] = MP_OBJ_NEW_SMALL_INT(buf.st_gid); // st_gid
|
||||
t->items[6] = mp_obj_new_int_from_uint(buf.st_size); // st_size
|
||||
t->items[7] = MP_OBJ_NEW_SMALL_INT(buf.st_atime); // st_atime
|
||||
t->items[8] = MP_OBJ_NEW_SMALL_INT(buf.st_mtime); // st_mtime
|
||||
t->items[9] = MP_OBJ_NEW_SMALL_INT(buf.st_ctime); // st_ctime
|
||||
return MP_OBJ_FROM_PTR(t);
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(mp_posix_stat_obj, mp_posix_stat);
|
||||
|
||||
static uint32_t calc_crc32(const char* pathname)
|
||||
{
|
||||
#define CALC_BUFFER_SIZE 512
|
||||
extern uint32_t mp_calc_crc32(uint32_t crc, const void *buf, size_t len);
|
||||
|
||||
int fd;
|
||||
uint32_t temp_crc = 0;
|
||||
void *buffer = malloc(CALC_BUFFER_SIZE);
|
||||
|
||||
if (buffer == RT_NULL)
|
||||
{
|
||||
mp_raise_OSError(MP_ENOMEM);
|
||||
}
|
||||
|
||||
fd = open(pathname, O_RDONLY, 0);
|
||||
if (fd < 0)
|
||||
{
|
||||
return -MP_EINVAL;
|
||||
}
|
||||
|
||||
while (1)
|
||||
{
|
||||
int len = read(fd, buffer, CALC_BUFFER_SIZE);
|
||||
if (len < 0)
|
||||
{
|
||||
close(fd);
|
||||
return -MP_EIO;
|
||||
}
|
||||
else if (len == 0)
|
||||
break;
|
||||
|
||||
temp_crc = mp_calc_crc32(temp_crc, buffer, len);
|
||||
}
|
||||
|
||||
close(fd);
|
||||
free(buffer);
|
||||
|
||||
return temp_crc;
|
||||
}
|
||||
|
||||
mp_obj_t mp_posix_file_crc32(mp_obj_t path_in) {
|
||||
extern void mp_hex_to_str(char *pbDest, char *pbSrc, int nLen);
|
||||
|
||||
uint32_t value = 0;
|
||||
char str[9];
|
||||
const char *createpath = mp_obj_str_get_str(path_in);
|
||||
|
||||
value = calc_crc32((char *)createpath);
|
||||
mp_hex_to_str(str,(char *)&value, 4);
|
||||
|
||||
return mp_obj_new_str(str, strlen(str));
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(mp_posix_file_crc32_obj, mp_posix_file_crc32);
|
||||
|
||||
mp_import_stat_t mp_posix_import_stat(const char *path) {
|
||||
|
||||
struct stat stat;
|
||||
|
||||
if (dfs_file_stat(path, &stat) == 0) {
|
||||
if (S_ISDIR(stat.st_mode)) {
|
||||
return MP_IMPORT_STAT_DIR;
|
||||
} else {
|
||||
return MP_IMPORT_STAT_FILE;
|
||||
}
|
||||
} else {
|
||||
return MP_IMPORT_STAT_NO_EXIST;
|
||||
}
|
||||
}
|
||||
|
||||
#endif //MICROPY_MODUOS_FILE
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 SummerGift <zhangyuan@rt-thread.com>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef MICROPY_INCLUDED_PY_MODUOS_FILE_H
|
||||
#define MICROPY_INCLUDED_PY_MODUOS_FILE_H
|
||||
|
||||
#include "py/lexer.h"
|
||||
#include "py/obj.h"
|
||||
|
||||
// MicroPython's port-standardized versions of stat constants
|
||||
#define MP_S_IFDIR (0x4000)
|
||||
#define MP_S_IFREG (0x8000)
|
||||
|
||||
// constants for block protocol ioctl
|
||||
#define BP_IOCTL_INIT (1)
|
||||
#define BP_IOCTL_DEINIT (2)
|
||||
#define BP_IOCTL_SYNC (3)
|
||||
#define BP_IOCTL_SEC_COUNT (4)
|
||||
#define BP_IOCTL_SEC_SIZE (5)
|
||||
|
||||
mp_obj_t mp_posix_mount(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args);
|
||||
mp_obj_t mp_posix_umount(mp_obj_t mnt_in);
|
||||
mp_obj_t mp_posix_open(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args);
|
||||
mp_obj_t mp_posix_chdir(mp_obj_t path_in);
|
||||
mp_obj_t mp_posix_getcwd(void);
|
||||
mp_obj_t mp_posix_listdir(size_t n_args, const mp_obj_t *args);
|
||||
mp_obj_t mp_posix_mkdir(mp_obj_t path_in);
|
||||
mp_obj_t mp_posix_remove(uint n_args, const mp_obj_t *arg);
|
||||
mp_obj_t mp_posix_rename(mp_obj_t old_path_in, mp_obj_t new_path_in);
|
||||
mp_obj_t mp_posix_rmdir(uint n_args, const mp_obj_t *arg);
|
||||
mp_obj_t mp_posix_stat(mp_obj_t path_in);
|
||||
mp_obj_t mp_posix_statvfs(mp_obj_t path_in);
|
||||
mp_obj_t mp_posix_file_crc32(mp_obj_t path_in);
|
||||
mp_obj_t mp_posix_mkfs(size_t n_args, const mp_obj_t *args);
|
||||
|
||||
MP_DECLARE_CONST_FUN_OBJ_KW(mp_posix_mount_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_1(mp_posix_umount_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_KW(mp_posix_open_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_1(mp_posix_chdir_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_0(mp_posix_getcwd_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_posix_listdir_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_1(mp_posix_mkdir_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_VAR(mp_posix_remove_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_2(mp_posix_rename_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_VAR(mp_posix_rmdir_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_1(mp_posix_stat_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_1(mp_posix_statvfs_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_1(mp_posix_file_crc32_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_posix_mkfs_obj);
|
||||
#endif // MICROPY_INCLUDED_PY_MODUOS_FILE_H
|
||||
@@ -0,0 +1,599 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018 Armink (armink.ztl@gmail.com)
|
||||
*
|
||||
* 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 "py/mpconfig.h"
|
||||
|
||||
#if MICROPY_PY_USOCKET
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <netdb.h>
|
||||
#include <sys/socket.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/select.h>
|
||||
|
||||
#include "py/objtuple.h"
|
||||
#include "py/objlist.h"
|
||||
#include "py/runtime.h"
|
||||
#include "py/mperrno.h"
|
||||
#include "py/stream.h"
|
||||
#include "py/objstr.h"
|
||||
#include "py/builtin.h"
|
||||
|
||||
#include "lib/netutils/netutils.h"
|
||||
#include "modnetwork.h"
|
||||
|
||||
#define SOCKET_POLL_US (100000)
|
||||
|
||||
// socket class
|
||||
typedef struct _socket_obj_t {
|
||||
mp_obj_base_t base;
|
||||
int fd;
|
||||
uint8_t domain;
|
||||
uint8_t type;
|
||||
uint8_t proto;
|
||||
bool peer_closed;
|
||||
unsigned int retries;
|
||||
} socket_obj_t;
|
||||
|
||||
STATIC const mp_obj_type_t socket_type;
|
||||
|
||||
STATIC void _socket_settimeout(socket_obj_t *sock, uint64_t timeout_ms);
|
||||
|
||||
NORETURN static void exception_from_errno(int _errno) {
|
||||
// Here we need to convert from lwip errno values to MicroPython's standard ones
|
||||
if (_errno == EINPROGRESS) {
|
||||
_errno = MP_EINPROGRESS;
|
||||
}
|
||||
mp_raise_OSError(_errno);
|
||||
}
|
||||
|
||||
static inline void check_for_exceptions(void) {
|
||||
mp_handle_pending(true);
|
||||
}
|
||||
|
||||
static int _socket_getaddrinfo2(const mp_obj_t host, const mp_obj_t portx, struct addrinfo **resp) {
|
||||
const struct addrinfo hints = {
|
||||
.ai_family = AF_INET,
|
||||
.ai_socktype = SOCK_STREAM,
|
||||
};
|
||||
|
||||
mp_obj_t port = portx;
|
||||
if (MP_OBJ_IS_SMALL_INT(port)) {
|
||||
// This is perverse, because lwip_getaddrinfo promptly converts it back to an int, but
|
||||
// that's the API we have to work with ...
|
||||
port = mp_obj_str_binary_op(MP_BINARY_OP_MODULO, mp_obj_new_str_via_qstr("%s", 2), port);
|
||||
}
|
||||
|
||||
const char *host_str = mp_obj_str_get_str(host);
|
||||
const char *port_str = mp_obj_str_get_str(port);
|
||||
|
||||
if (host_str[0] == '\0') {
|
||||
// a host of "" is equivalent to the default/all-local IP address
|
||||
host_str = "0.0.0.0";
|
||||
}
|
||||
|
||||
MP_THREAD_GIL_EXIT();
|
||||
int res = getaddrinfo(host_str, port_str, &hints, resp);
|
||||
MP_THREAD_GIL_ENTER();
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int _socket_getaddrinfo(const mp_obj_t addrtuple, struct addrinfo **resp) {
|
||||
mp_uint_t len = 0;
|
||||
mp_obj_t *elem;
|
||||
mp_obj_get_array(addrtuple, &len, &elem);
|
||||
if (len != 2) return -1;
|
||||
return _socket_getaddrinfo2(elem[0], elem[1], resp);
|
||||
}
|
||||
|
||||
STATIC mp_obj_t socket_bind(const mp_obj_t arg0, const mp_obj_t arg1) {
|
||||
socket_obj_t *self = MP_OBJ_TO_PTR(arg0);
|
||||
struct addrinfo *res;
|
||||
_socket_getaddrinfo(arg1, &res);
|
||||
int r = bind(self->fd, res->ai_addr, res->ai_addrlen);
|
||||
freeaddrinfo(res);
|
||||
if (r < 0) exception_from_errno(errno);
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_bind_obj, socket_bind);
|
||||
|
||||
STATIC mp_obj_t socket_listen(const mp_obj_t arg0, const mp_obj_t arg1) {
|
||||
socket_obj_t *self = MP_OBJ_TO_PTR(arg0);
|
||||
int backlog = mp_obj_get_int(arg1);
|
||||
int r = listen(self->fd, backlog);
|
||||
if (r < 0) exception_from_errno(errno);
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_listen_obj, socket_listen);
|
||||
|
||||
STATIC mp_obj_t socket_accept(const mp_obj_t arg0) {
|
||||
socket_obj_t *self = MP_OBJ_TO_PTR(arg0);
|
||||
|
||||
struct sockaddr addr;
|
||||
socklen_t addr_len = sizeof(addr);
|
||||
|
||||
int new_fd = -1;
|
||||
for (int i = 0; i <= self->retries; i++) {
|
||||
MP_THREAD_GIL_EXIT();
|
||||
new_fd = accept(self->fd, &addr, &addr_len);
|
||||
MP_THREAD_GIL_ENTER();
|
||||
if (new_fd >= 0) break;
|
||||
// if (errno != EAGAIN) exception_from_errno(errno);
|
||||
check_for_exceptions();
|
||||
}
|
||||
if (new_fd < 0) mp_raise_OSError(MP_ETIMEDOUT);
|
||||
|
||||
// create new socket object
|
||||
socket_obj_t *sock = m_new_obj_with_finaliser(socket_obj_t);
|
||||
sock->base.type = self->base.type;
|
||||
sock->fd = new_fd;
|
||||
sock->domain = self->domain;
|
||||
sock->type = self->type;
|
||||
sock->proto = self->proto;
|
||||
sock->peer_closed = false;
|
||||
_socket_settimeout(sock, UINT64_MAX);
|
||||
|
||||
// make the return value
|
||||
uint8_t *ip = (uint8_t*)&((struct sockaddr_in*)&addr)->sin_addr;
|
||||
mp_uint_t port = ntohs(((struct sockaddr_in*)&addr)->sin_port);
|
||||
mp_obj_tuple_t *client = mp_obj_new_tuple(2, NULL);
|
||||
client->items[0] = sock;
|
||||
client->items[1] = netutils_format_inet_addr(ip, port, NETUTILS_BIG);
|
||||
|
||||
return client;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(socket_accept_obj, socket_accept);
|
||||
|
||||
STATIC mp_obj_t socket_connect(const mp_obj_t arg0, const mp_obj_t arg1) {
|
||||
socket_obj_t *self = MP_OBJ_TO_PTR(arg0);
|
||||
struct addrinfo *res;
|
||||
_socket_getaddrinfo(arg1, &res);
|
||||
MP_THREAD_GIL_EXIT();
|
||||
int r = connect(self->fd, res->ai_addr, res->ai_addrlen);
|
||||
MP_THREAD_GIL_ENTER();
|
||||
freeaddrinfo(res);
|
||||
if (r != 0) {
|
||||
exception_from_errno(errno);
|
||||
}
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_connect_obj, socket_connect);
|
||||
|
||||
STATIC mp_obj_t socket_setsockopt(size_t n_args, const mp_obj_t *args) {
|
||||
(void)n_args; // always 4
|
||||
socket_obj_t *self = MP_OBJ_TO_PTR(args[0]);
|
||||
|
||||
int opt = mp_obj_get_int(args[2]);
|
||||
|
||||
switch (opt) {
|
||||
// level: SOL_SOCKET
|
||||
case SO_REUSEADDR: {
|
||||
int val = mp_obj_get_int(args[3]);
|
||||
int ret = setsockopt(self->fd, SOL_SOCKET, opt, &val, sizeof(int));
|
||||
if (ret != 0) {
|
||||
exception_from_errno(errno);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// level: IPPROTO_IP
|
||||
case IP_ADD_MEMBERSHIP: {
|
||||
mp_buffer_info_t bufinfo;
|
||||
mp_get_buffer_raise(args[3], &bufinfo, MP_BUFFER_READ);
|
||||
if (bufinfo.len != sizeof(ip4_addr_t) * 2) {
|
||||
mp_raise_ValueError(NULL);
|
||||
}
|
||||
|
||||
// // POSIX setsockopt has order: group addr, if addr, lwIP has it vice-versa
|
||||
// err_t err = igmp_joingroup((const ip4_addr_t*)bufinfo.buf + 1, bufinfo.buf);
|
||||
// if (err != ERR_OK) {
|
||||
// mp_raise_OSError(-err);
|
||||
// }
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
mp_printf(&mp_plat_print, "Warning: setsockopt() option not implemented\n");
|
||||
}
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(socket_setsockopt_obj, 4, 4, socket_setsockopt);
|
||||
|
||||
STATIC void _socket_settimeout(socket_obj_t *sock, uint64_t timeout_ms) {
|
||||
// Rather than waiting for the entire timeout specified, we wait sock->retries times
|
||||
// for SOCKET_POLL_US each, checking for a MicroPython interrupt between timeouts.
|
||||
// with SOCKET_POLL_MS == 100ms, sock->retries allows for timeouts up to 13 years.
|
||||
// if timeout_ms == UINT64_MAX, wait forever.
|
||||
sock->retries = (timeout_ms == UINT64_MAX) ? UINT_MAX : timeout_ms * 1000 / SOCKET_POLL_US;
|
||||
|
||||
struct timeval timeout = {
|
||||
.tv_sec = 0,
|
||||
.tv_usec = timeout_ms ? SOCKET_POLL_US : 0
|
||||
};
|
||||
setsockopt(sock->fd, SOL_SOCKET, SO_SNDTIMEO, (const void *)&timeout, sizeof(timeout));
|
||||
setsockopt(sock->fd, SOL_SOCKET, SO_RCVTIMEO, (const void *)&timeout, sizeof(timeout));
|
||||
fcntl(sock->fd, F_SETFL, timeout_ms ? 0 : O_NONBLOCK);
|
||||
}
|
||||
|
||||
STATIC mp_obj_t socket_settimeout(const mp_obj_t arg0, const mp_obj_t arg1) {
|
||||
socket_obj_t *self = MP_OBJ_TO_PTR(arg0);
|
||||
if (arg1 == mp_const_none) _socket_settimeout(self, UINT64_MAX);
|
||||
else _socket_settimeout(self, mp_obj_get_float(arg1) * 1000L);
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_settimeout_obj, socket_settimeout);
|
||||
|
||||
STATIC mp_obj_t socket_setblocking(const mp_obj_t arg0, const mp_obj_t arg1) {
|
||||
socket_obj_t *self = MP_OBJ_TO_PTR(arg0);
|
||||
if (mp_obj_is_true(arg1)) _socket_settimeout(self, UINT64_MAX);
|
||||
else _socket_settimeout(self, 0);
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_setblocking_obj, socket_setblocking);
|
||||
|
||||
// XXX this can end up waiting a very long time if the content is dribbled in one character
|
||||
// at a time, as the timeout resets each time a recvfrom succeeds ... this is probably not
|
||||
// good behaviour.
|
||||
STATIC mp_uint_t _socket_read_data(mp_obj_t self_in, void *buf, size_t size,
|
||||
struct sockaddr *from, socklen_t *from_len, int *errcode) {
|
||||
socket_obj_t *sock = MP_OBJ_TO_PTR(self_in);
|
||||
|
||||
// If the peer closed the connection then the lwIP socket API will only return "0" once
|
||||
// from lwip_recvfrom_r and then block on subsequent calls. To emulate POSIX behaviour,
|
||||
// which continues to return "0" for each call on a closed socket, we set a flag when
|
||||
// the peer closed the socket.
|
||||
if (sock->peer_closed) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// XXX Would be nicer to use RTC to handle timeouts
|
||||
for (int i = 0; i <= sock->retries; ++i) {
|
||||
MP_THREAD_GIL_EXIT();
|
||||
int r = recvfrom(sock->fd, buf, size, 0, from, from_len);
|
||||
MP_THREAD_GIL_ENTER();
|
||||
if (r == 0) {
|
||||
sock->peer_closed = true;
|
||||
}
|
||||
if (r >= 0) {
|
||||
return r;
|
||||
}
|
||||
// if (errno != EWOULDBLOCK) {
|
||||
// *errcode = errno;
|
||||
// return MP_STREAM_ERROR;
|
||||
// }
|
||||
check_for_exceptions();
|
||||
}
|
||||
|
||||
*errcode = sock->retries == 0 ? MP_EWOULDBLOCK : MP_ETIMEDOUT;
|
||||
return MP_STREAM_ERROR;
|
||||
}
|
||||
|
||||
mp_obj_t _socket_recvfrom(mp_obj_t self_in, mp_obj_t len_in,
|
||||
struct sockaddr *from, socklen_t *from_len) {
|
||||
size_t len = mp_obj_get_int(len_in);
|
||||
vstr_t vstr;
|
||||
vstr_init_len(&vstr, len);
|
||||
|
||||
int errcode;
|
||||
mp_uint_t ret = _socket_read_data(self_in, vstr.buf, len, from, from_len, &errcode);
|
||||
if (ret == MP_STREAM_ERROR) {
|
||||
exception_from_errno(errcode);
|
||||
}
|
||||
|
||||
vstr.len = ret;
|
||||
return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
|
||||
}
|
||||
|
||||
STATIC mp_obj_t socket_recv(mp_obj_t self_in, mp_obj_t len_in) {
|
||||
return _socket_recvfrom(self_in, len_in, NULL, NULL);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_recv_obj, socket_recv);
|
||||
|
||||
STATIC mp_obj_t socket_recvfrom(mp_obj_t self_in, mp_obj_t len_in) {
|
||||
struct sockaddr from;
|
||||
socklen_t fromlen = sizeof(from);
|
||||
|
||||
mp_obj_t tuple[2];
|
||||
tuple[0] = _socket_recvfrom(self_in, len_in, &from, &fromlen);
|
||||
|
||||
uint8_t *ip = (uint8_t*)&((struct sockaddr_in*)&from)->sin_addr;
|
||||
mp_uint_t port = ntohs(((struct sockaddr_in*)&from)->sin_port);
|
||||
tuple[1] = netutils_format_inet_addr(ip, port, NETUTILS_BIG);
|
||||
|
||||
return mp_obj_new_tuple(2, tuple);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_recvfrom_obj, socket_recvfrom);
|
||||
|
||||
STATIC int _socket_send(socket_obj_t *sock, const char *data, size_t datalen) {
|
||||
int sentlen = 0;
|
||||
for (int i = 0; i <= sock->retries && sentlen < datalen; i++) {
|
||||
MP_THREAD_GIL_EXIT();
|
||||
int r = send(sock->fd, data + sentlen, datalen - sentlen, 0);
|
||||
MP_THREAD_GIL_ENTER();
|
||||
if (r < 0 && errno != EWOULDBLOCK) exception_from_errno(errno);
|
||||
if (r > 0) sentlen += r;
|
||||
check_for_exceptions();
|
||||
}
|
||||
if (sentlen == 0) mp_raise_OSError(MP_ETIMEDOUT);
|
||||
return sentlen;
|
||||
}
|
||||
|
||||
STATIC mp_obj_t socket_send(const mp_obj_t arg0, const mp_obj_t arg1) {
|
||||
socket_obj_t *sock = MP_OBJ_TO_PTR(arg0);
|
||||
mp_uint_t datalen;
|
||||
const char *data = mp_obj_str_get_data(arg1, &datalen);
|
||||
int r = _socket_send(sock, data, datalen);
|
||||
return mp_obj_new_int(r);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_send_obj, socket_send);
|
||||
|
||||
STATIC mp_obj_t socket_sendall(const mp_obj_t arg0, const mp_obj_t arg1) {
|
||||
// XXX behaviour when nonblocking (see extmod/modlwip.c)
|
||||
// XXX also timeout behaviour.
|
||||
socket_obj_t *sock = MP_OBJ_TO_PTR(arg0);
|
||||
mp_buffer_info_t bufinfo;
|
||||
mp_get_buffer_raise(arg1, &bufinfo, MP_BUFFER_READ);
|
||||
int r = _socket_send(sock, bufinfo.buf, bufinfo.len);
|
||||
if (r < bufinfo.len) mp_raise_OSError(MP_ETIMEDOUT);
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_sendall_obj, socket_sendall);
|
||||
|
||||
STATIC mp_obj_t socket_sendto(mp_obj_t self_in, mp_obj_t data_in, mp_obj_t addr_in) {
|
||||
socket_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
|
||||
// get the buffer to send
|
||||
mp_buffer_info_t bufinfo;
|
||||
mp_get_buffer_raise(data_in, &bufinfo, MP_BUFFER_READ);
|
||||
|
||||
// create the destination address
|
||||
struct sockaddr_in to;
|
||||
to.sin_len = sizeof(to);
|
||||
to.sin_family = AF_INET;
|
||||
to.sin_port = htons(netutils_parse_inet_addr(addr_in, (uint8_t*)&to.sin_addr, NETUTILS_BIG));
|
||||
|
||||
// send the data
|
||||
for (int i=0; i<=self->retries; i++) {
|
||||
MP_THREAD_GIL_EXIT();
|
||||
int ret = sendto(self->fd, bufinfo.buf, bufinfo.len, 0, (struct sockaddr*)&to, sizeof(to));
|
||||
MP_THREAD_GIL_ENTER();
|
||||
if (ret > 0) return mp_obj_new_int_from_uint(ret);
|
||||
if (ret == -1 && errno != EWOULDBLOCK) {
|
||||
exception_from_errno(errno);
|
||||
}
|
||||
check_for_exceptions();
|
||||
}
|
||||
mp_raise_OSError(MP_ETIMEDOUT);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_3(socket_sendto_obj, socket_sendto);
|
||||
|
||||
STATIC mp_obj_t socket_fileno(const mp_obj_t arg0) {
|
||||
socket_obj_t *self = MP_OBJ_TO_PTR(arg0);
|
||||
return mp_obj_new_int(self->fd);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(socket_fileno_obj, socket_fileno);
|
||||
|
||||
STATIC mp_obj_t socket_makefile(size_t n_args, const mp_obj_t *args) {
|
||||
(void)n_args;
|
||||
return args[0];
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(socket_makefile_obj, 1, 3, socket_makefile);
|
||||
|
||||
STATIC mp_uint_t socket_stream_read(mp_obj_t self_in, void *buf, mp_uint_t size, int *errcode) {
|
||||
return _socket_read_data(self_in, buf, size, NULL, NULL, errcode);
|
||||
}
|
||||
|
||||
STATIC mp_uint_t socket_stream_write(mp_obj_t self_in, const void *buf, mp_uint_t size, int *errcode) {
|
||||
socket_obj_t *sock = self_in;
|
||||
for (int i = 0; i <= sock->retries; i++) {
|
||||
MP_THREAD_GIL_EXIT();
|
||||
int r = send(sock->fd, buf, size, 0);
|
||||
MP_THREAD_GIL_ENTER();
|
||||
if (r > 0) return r;
|
||||
if (r < 0 && errno != EWOULDBLOCK) { *errcode = errno; return MP_STREAM_ERROR; }
|
||||
check_for_exceptions();
|
||||
}
|
||||
*errcode = sock->retries == 0 ? MP_EWOULDBLOCK : MP_ETIMEDOUT;
|
||||
return MP_STREAM_ERROR;
|
||||
}
|
||||
|
||||
STATIC mp_uint_t socket_stream_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int *errcode) {
|
||||
socket_obj_t * socket = self_in;
|
||||
if (request == MP_STREAM_POLL) {
|
||||
|
||||
fd_set rfds; FD_ZERO(&rfds);
|
||||
fd_set wfds; FD_ZERO(&wfds);
|
||||
fd_set efds; FD_ZERO(&efds);
|
||||
struct timeval timeout = { .tv_sec = 0, .tv_usec = 0 };
|
||||
if (arg & MP_STREAM_POLL_RD) FD_SET(socket->fd, &rfds);
|
||||
if (arg & MP_STREAM_POLL_WR) FD_SET(socket->fd, &wfds);
|
||||
if (arg & MP_STREAM_POLL_HUP) FD_SET(socket->fd, &efds);
|
||||
|
||||
MP_THREAD_GIL_EXIT();
|
||||
int r = select((socket->fd)+1, &rfds, &wfds, &efds, &timeout);
|
||||
MP_THREAD_GIL_ENTER();
|
||||
if (r < 0) {
|
||||
*errcode = MP_EIO;
|
||||
return MP_STREAM_ERROR;
|
||||
}
|
||||
|
||||
mp_uint_t ret = 0;
|
||||
if (FD_ISSET(socket->fd, &rfds)) ret |= MP_STREAM_POLL_RD;
|
||||
if (FD_ISSET(socket->fd, &wfds)) ret |= MP_STREAM_POLL_WR;
|
||||
if (FD_ISSET(socket->fd, &efds)) ret |= MP_STREAM_POLL_HUP;
|
||||
return ret;
|
||||
} else if (request == MP_STREAM_CLOSE) {
|
||||
if (socket->fd >= 0) {
|
||||
int ret = closesocket(socket->fd);
|
||||
if (ret != 0) {
|
||||
*errcode = errno;
|
||||
return MP_STREAM_ERROR;
|
||||
}
|
||||
socket->fd = -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
*errcode = MP_EINVAL;
|
||||
return MP_STREAM_ERROR;
|
||||
}
|
||||
|
||||
STATIC const mp_rom_map_elem_t socket_locals_dict_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mp_stream_close_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&mp_stream_close_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_bind), MP_ROM_PTR(&socket_bind_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_listen), MP_ROM_PTR(&socket_listen_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_accept), MP_ROM_PTR(&socket_accept_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_connect), MP_ROM_PTR(&socket_connect_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_send), MP_ROM_PTR(&socket_send_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_sendall), MP_ROM_PTR(&socket_sendall_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_sendto), MP_ROM_PTR(&socket_sendto_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_recv), MP_ROM_PTR(&socket_recv_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_recvfrom), MP_ROM_PTR(&socket_recvfrom_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_setsockopt), MP_ROM_PTR(&socket_setsockopt_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_settimeout), MP_ROM_PTR(&socket_settimeout_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_setblocking), MP_ROM_PTR(&socket_setblocking_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_makefile), MP_ROM_PTR(&socket_makefile_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_fileno), MP_ROM_PTR(&socket_fileno_obj) },
|
||||
|
||||
{ MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) },
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(socket_locals_dict, socket_locals_dict_table);
|
||||
|
||||
STATIC const mp_stream_p_t socket_stream_p = {
|
||||
.read = socket_stream_read,
|
||||
.write = socket_stream_write,
|
||||
.ioctl = socket_stream_ioctl
|
||||
};
|
||||
|
||||
STATIC const mp_obj_type_t socket_type = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_socket,
|
||||
.protocol = &socket_stream_p,
|
||||
.locals_dict = (mp_obj_t)&socket_locals_dict,
|
||||
};
|
||||
|
||||
STATIC mp_obj_t get_socket(size_t n_args, const mp_obj_t *args) {
|
||||
socket_obj_t *sock = m_new_obj_with_finaliser(socket_obj_t);
|
||||
sock->base.type = &socket_type;
|
||||
sock->domain = AF_INET;
|
||||
sock->type = SOCK_STREAM;
|
||||
sock->proto = 0;
|
||||
sock->peer_closed = false;
|
||||
if (n_args > 0) {
|
||||
sock->domain = mp_obj_get_int(args[0]);
|
||||
if (n_args > 1) {
|
||||
sock->type = mp_obj_get_int(args[1]);
|
||||
if (n_args > 2) {
|
||||
sock->proto = mp_obj_get_int(args[2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sock->fd = socket(sock->domain, sock->type, sock->proto);
|
||||
if (sock->fd < 0) {
|
||||
exception_from_errno(errno);
|
||||
}
|
||||
_socket_settimeout(sock, UINT64_MAX);
|
||||
|
||||
return MP_OBJ_FROM_PTR(sock);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(get_socket_obj, 0, 3, get_socket);
|
||||
|
||||
/******************************************************************************/
|
||||
// usocket module
|
||||
// function usocket.getaddrinfo(host, port)
|
||||
STATIC mp_obj_t mod_usocket_getaddrinfo(uint n_args, const mp_obj_t *arg) {
|
||||
// TODO support additional args beyond the first two
|
||||
size_t hlen;
|
||||
int ret;
|
||||
const char *host = mp_obj_str_get_data(arg[0], &hlen);
|
||||
mp_int_t port = mp_obj_get_int(arg[1]);
|
||||
struct addrinfo hint, *res = NULL;
|
||||
memset(&hint, 0, sizeof(hint));
|
||||
|
||||
MP_THREAD_GIL_EXIT();
|
||||
ret = getaddrinfo(host, NULL, &hint, &res);
|
||||
MP_THREAD_GIL_ENTER();
|
||||
if (ret != 0) {
|
||||
mp_printf(&mp_plat_print, "getaddrinfo err: %d '%s'\n", ret, host);
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "no available netif"));
|
||||
}
|
||||
|
||||
mp_obj_tuple_t *tuple = mp_obj_new_tuple(5, NULL);
|
||||
tuple->items[0] = MP_OBJ_NEW_SMALL_INT(MOD_NETWORK_AF_INET);
|
||||
tuple->items[1] = MP_OBJ_NEW_SMALL_INT(MOD_NETWORK_SOCK_STREAM);
|
||||
tuple->items[2] = MP_OBJ_NEW_SMALL_INT(0);
|
||||
tuple->items[3] = MP_OBJ_NEW_QSTR(MP_QSTR_);
|
||||
|
||||
mp_obj_t tuple_addr[2] = {
|
||||
tuple_addr[0] = netutils_format_ipv4_addr((uint8_t *)((res->ai_addr->sa_data) + 2), NETUTILS_BIG),
|
||||
tuple_addr[1] = mp_obj_new_int(port),
|
||||
};
|
||||
|
||||
tuple->items[4] = mp_obj_new_tuple(2, tuple_addr);
|
||||
freeaddrinfo(res);
|
||||
|
||||
return mp_obj_new_list(1, (mp_obj_t*) &tuple);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_usocket_getaddrinfo_obj, 2, 6, mod_usocket_getaddrinfo);
|
||||
|
||||
STATIC const mp_rom_map_elem_t mp_module_socket_globals_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_usocket) },
|
||||
|
||||
{ MP_ROM_QSTR(MP_QSTR_socket), MP_ROM_PTR(&get_socket_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_getaddrinfo), MP_ROM_PTR(&mod_usocket_getaddrinfo_obj) },
|
||||
|
||||
{ MP_ROM_QSTR(MP_QSTR_AF_INET), MP_ROM_INT(AF_INET) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_AF_INET6), MP_ROM_INT(AF_INET6) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_SOCK_STREAM), MP_ROM_INT(SOCK_STREAM) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_SOCK_DGRAM), MP_ROM_INT(SOCK_DGRAM) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_SOCK_RAW), MP_ROM_INT(SOCK_RAW) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_IPPROTO_TCP), MP_ROM_INT(IPPROTO_TCP) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_IPPROTO_UDP), MP_ROM_INT(IPPROTO_UDP) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_IPPROTO_IP), MP_ROM_INT(IPPROTO_IP) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_SOL_SOCKET), MP_ROM_INT(SOL_SOCKET) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_SO_REUSEADDR), MP_ROM_INT(SO_REUSEADDR) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_IP_ADD_MEMBERSHIP), MP_ROM_INT(IP_ADD_MEMBERSHIP) },
|
||||
};
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(mp_module_socket_globals, mp_module_socket_globals_table);
|
||||
|
||||
const mp_obj_module_t mp_module_usocket = {
|
||||
.base = { &mp_type_module },
|
||||
.globals = (mp_obj_dict_t*)&mp_module_socket_globals,
|
||||
};
|
||||
|
||||
#endif // MICROPY_PY_USOCKET
|
||||
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2019 SummerGift (SummerGift@qq.com)
|
||||
*
|
||||
* 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 "py/mpconfig.h"
|
||||
|
||||
static const uint32_t crc32_table[] =
|
||||
{
|
||||
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
|
||||
0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
|
||||
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
|
||||
0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
|
||||
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
|
||||
0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
|
||||
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
|
||||
0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
|
||||
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
|
||||
0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
|
||||
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
|
||||
0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
|
||||
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
|
||||
0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
|
||||
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
|
||||
0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
|
||||
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
|
||||
0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
|
||||
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
|
||||
0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
|
||||
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
|
||||
0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
|
||||
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
|
||||
0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
|
||||
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
|
||||
0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
|
||||
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
|
||||
0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
|
||||
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
|
||||
0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
|
||||
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
|
||||
0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
|
||||
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
|
||||
0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
|
||||
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
|
||||
0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
|
||||
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
|
||||
0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
|
||||
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
|
||||
0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
|
||||
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
|
||||
0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
|
||||
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculate the CRC32 value of a memory buffer.
|
||||
*
|
||||
* @param crc accumulated CRC32 value, must be 0 on first call
|
||||
* @param buf buffer to calculate CRC32 value for
|
||||
* @param len bytes in buffer
|
||||
*
|
||||
* @return calculated CRC32 value
|
||||
*/
|
||||
uint32_t mp_calc_crc32(uint32_t crc, const void *buf, size_t len)
|
||||
{
|
||||
const uint8_t *p;
|
||||
|
||||
p = (const uint8_t *)buf;
|
||||
crc = crc ^ ~0U;
|
||||
|
||||
while (len--) {
|
||||
crc = crc32_table[(crc ^ *p++) & 0xFF] ^ (crc >> 8);
|
||||
}
|
||||
|
||||
return crc ^ ~0U;
|
||||
}
|
||||
|
||||
void mp_hex_to_str(char *pbDest, char *pbSrc, int nLen)
|
||||
{
|
||||
char ddl,ddh;
|
||||
int i;
|
||||
|
||||
for (i=0; i<nLen; i++)
|
||||
{
|
||||
ddh = 48 + pbSrc[i] / 16;
|
||||
ddl = 48 + pbSrc[i] % 16;
|
||||
if (ddh > 57) ddh = ddh + 7;
|
||||
if (ddl > 57) ddl = ddl + 7;
|
||||
pbDest[i*2] = ddh;
|
||||
pbDest[i*2+1] = ddl;
|
||||
}
|
||||
|
||||
pbDest[nLen*2] = '\0';
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Armink (armink.ztl@gmail.com)
|
||||
*
|
||||
* 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 "py/mpconfig.h"
|
||||
#if MICROPY_PY_UTIME
|
||||
|
||||
#include <rtthread.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include "py/runtime.h"
|
||||
#include "py/smallint.h"
|
||||
#include "py/mphal.h"
|
||||
#include "extmod/utime_mphal.h"
|
||||
#include "lib/timeutils/timeutils.h"
|
||||
#include <math.h>
|
||||
|
||||
STATIC mp_obj_t mod_time_time(void) {
|
||||
#if MICROPY_PY_BUILTINS_FLOAT
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, NULL);
|
||||
mp_float_t val = tv.tv_sec + (mp_float_t)tv.tv_usec / 1000000;
|
||||
return mp_obj_new_float(val);
|
||||
#else
|
||||
return mp_obj_new_int((mp_int_t)time(NULL));
|
||||
#endif
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_time_time_obj, mod_time_time);
|
||||
|
||||
STATIC mp_obj_t mod_time_localtime(size_t n_args, const mp_obj_t *args) {
|
||||
time_t t;
|
||||
if (n_args == 0) {
|
||||
t = time(NULL);
|
||||
} else {
|
||||
#if MICROPY_PY_BUILTINS_FLOAT
|
||||
mp_float_t val = mp_obj_get_float(args[0]);
|
||||
t = (time_t)MICROPY_FLOAT_C_FUN(trunc)(val);
|
||||
#else
|
||||
t = mp_obj_get_int(args[0]);
|
||||
#endif
|
||||
}
|
||||
struct tm *tm = localtime(&t);
|
||||
|
||||
mp_obj_t ret = mp_obj_new_tuple(9, NULL);
|
||||
|
||||
mp_obj_tuple_t *tuple = MP_OBJ_TO_PTR(ret);
|
||||
tuple->items[0] = MP_OBJ_NEW_SMALL_INT(tm->tm_year + 1900);
|
||||
tuple->items[1] = MP_OBJ_NEW_SMALL_INT(tm->tm_mon + 1);
|
||||
tuple->items[2] = MP_OBJ_NEW_SMALL_INT(tm->tm_mday);
|
||||
tuple->items[3] = MP_OBJ_NEW_SMALL_INT(tm->tm_hour);
|
||||
tuple->items[4] = MP_OBJ_NEW_SMALL_INT(tm->tm_min);
|
||||
tuple->items[5] = MP_OBJ_NEW_SMALL_INT(tm->tm_sec);
|
||||
int wday = tm->tm_wday - 1;
|
||||
if (wday < 0) {
|
||||
wday = 6;
|
||||
}
|
||||
tuple->items[6] = MP_OBJ_NEW_SMALL_INT(wday);
|
||||
tuple->items[7] = MP_OBJ_NEW_SMALL_INT(tm->tm_yday + 1);
|
||||
tuple->items[8] = MP_OBJ_NEW_SMALL_INT(tm->tm_isdst);
|
||||
|
||||
return ret;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_time_localtime_obj, 0, 1, mod_time_localtime);
|
||||
|
||||
/// \function mktime()
|
||||
/// This is inverse function of localtime. It's argument is a full 8-tuple
|
||||
/// which expresses a time as per localtime. It returns an integer which is
|
||||
/// the number of seconds since Jan 1, 2000.
|
||||
STATIC mp_obj_t time_mktime(mp_obj_t tuple) {
|
||||
|
||||
size_t len;
|
||||
mp_obj_t *elem;
|
||||
|
||||
mp_obj_get_array(tuple, &len, &elem);
|
||||
|
||||
// localtime generates a tuple of len 8. CPython uses 9, so we accept both.
|
||||
if (len < 8 || len > 9) {
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "mktime needs a tuple of length 8 or 9 (%d given)", len));
|
||||
}
|
||||
|
||||
return mp_obj_new_int_from_uint(timeutils_mktime(mp_obj_get_int(elem[0]),
|
||||
mp_obj_get_int(elem[1]), mp_obj_get_int(elem[2]), mp_obj_get_int(elem[3]),
|
||||
mp_obj_get_int(elem[4]), mp_obj_get_int(elem[5])));
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(time_mktime_obj, time_mktime);
|
||||
|
||||
STATIC const mp_rom_map_elem_t mp_module_time_globals_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_utime) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_sleep), MP_ROM_PTR(&mp_utime_sleep_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_sleep_ms), MP_ROM_PTR(&mp_utime_sleep_ms_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_sleep_us), MP_ROM_PTR(&mp_utime_sleep_us_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_time), MP_ROM_PTR(&mod_time_time_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_ticks_ms), MP_ROM_PTR(&mp_utime_ticks_ms_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_ticks_us), MP_ROM_PTR(&mp_utime_ticks_us_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_ticks_cpu), MP_ROM_PTR(&mp_utime_ticks_cpu_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_ticks_add), MP_ROM_PTR(&mp_utime_ticks_add_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_ticks_diff), MP_ROM_PTR(&mp_utime_ticks_diff_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_localtime), MP_ROM_PTR(&mod_time_localtime_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_mktime), MP_ROM_PTR(&time_mktime_obj) },
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(mp_module_time_globals, mp_module_time_globals_table);
|
||||
|
||||
const mp_obj_module_t mp_module_time = {
|
||||
.base = { &mp_type_module },
|
||||
.globals = (mp_obj_dict_t*)&mp_module_time_globals,
|
||||
};
|
||||
|
||||
#endif // MICROPY_PY_UTIME
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2019 SummerGift <summergift2019@gmail.com>
|
||||
*
|
||||
* 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 "py/runtime.h"
|
||||
|
||||
STATIC mp_obj_t add(
|
||||
mp_obj_t arg_1_obj,
|
||||
mp_obj_t arg_2_obj) {
|
||||
mp_int_t arg_1 = mp_obj_get_int(arg_1_obj);
|
||||
mp_int_t arg_2 = mp_obj_get_int(arg_2_obj);
|
||||
mp_int_t ret_val;
|
||||
|
||||
/* Your code start! */
|
||||
|
||||
ret_val = arg_1 + arg_2;
|
||||
|
||||
/* Your code end! */
|
||||
|
||||
return mp_obj_new_int(ret_val);
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_2(add_obj, add);
|
||||
|
||||
STATIC const mp_rom_map_elem_t mp_module_userfunc_globals_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_userfunc) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_add), MP_ROM_PTR(&add_obj) },
|
||||
};
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(mp_module_userfunc_globals, mp_module_userfunc_globals_table);
|
||||
|
||||
const mp_obj_module_t mp_module_userfunc = {
|
||||
.base = { &mp_type_module },
|
||||
.globals = (mp_obj_dict_t*)&mp_module_userfunc_globals,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user