Ubiquitous/RT-Thread_Fusion_XiUOS:change name from RT_Thread to RT-Thread_Fusion_XiUOS

This commit is contained in:
chunyexixiaoyu
2022-03-30 18:18:18 +08:00
parent 658feff666
commit 5a0ffaf193
624 changed files with 13 additions and 13 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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 */

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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,
};

View File

@@ -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

View File

@@ -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 */

View File

@@ -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

View 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

View File

@@ -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

View File

@@ -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';
}

View File

@@ -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

View File

@@ -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,
};