forked from xuos/xiuos
feat(Ubiquitous/RT_Thread): port micropython on RT-Thread for aiit-board
This commit is contained in:
@@ -0,0 +1,152 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2019 ChenYong (chenyong@rt-thread.com)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "py/nlr.h"
|
||||
#include "py/runtime.h"
|
||||
#include "modmachine.h"
|
||||
#include "mphalport.h"
|
||||
|
||||
#ifdef MICROPYTHON_USING_MACHINE_ADC
|
||||
|
||||
#include <rtthread.h>
|
||||
#include <drivers/adc.h>
|
||||
|
||||
extern const mp_obj_type_t machine_adc_type;
|
||||
|
||||
typedef struct _machine_adc_obj_t {
|
||||
mp_obj_base_t base;
|
||||
struct rt_adc_device *adc_device;
|
||||
uint8_t channel;
|
||||
uint8_t is_init;
|
||||
} machine_adc_obj_t;
|
||||
|
||||
STATIC void error_check(bool status, const char *msg) {
|
||||
if (!status) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, msg));
|
||||
}
|
||||
}
|
||||
|
||||
STATIC mp_obj_t machine_adc_make_new(const mp_obj_type_t *type,
|
||||
size_t n_args, size_t n_kw, const mp_obj_t *args) {
|
||||
// create ADC object from the given pin
|
||||
machine_adc_obj_t *self = m_new_obj(machine_adc_obj_t);
|
||||
struct rt_adc_device *adc_device = RT_NULL;
|
||||
char adc_dev_name[RT_NAME_MAX] = {0};
|
||||
rt_err_t result = RT_EOK;
|
||||
|
||||
// init machine adc object information
|
||||
self->channel = 0;
|
||||
self->is_init = RT_FALSE;
|
||||
self->base.type = &machine_adc_type;
|
||||
|
||||
mp_arg_check_num(n_args, n_kw, 1, 2, true);
|
||||
|
||||
// check input ADC device name or ID
|
||||
if (mp_obj_is_small_int(args[0])) {
|
||||
rt_snprintf(adc_dev_name, sizeof(adc_dev_name), "adc%d", mp_obj_get_int(args[0]));
|
||||
} else if (mp_obj_is_qstr(args[0])) {
|
||||
rt_strncpy(adc_dev_name, mp_obj_str_get_str(args[0]), RT_NAME_MAX);
|
||||
} else {
|
||||
error_check(0, "Input ADC device name or ID error.");
|
||||
}
|
||||
|
||||
adc_device = (struct rt_adc_device *) rt_device_find(adc_dev_name);
|
||||
if (adc_device == RT_NULL || adc_device->parent.type != RT_Device_Class_Miscellaneous) {
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError,
|
||||
"ADC(%s) don't exist", adc_dev_name));
|
||||
}
|
||||
self->adc_device = adc_device;
|
||||
|
||||
if (n_args == 2) {
|
||||
self->channel = mp_obj_get_int(args[1]);
|
||||
result = rt_adc_enable(self->adc_device, self->channel);
|
||||
error_check(result == RT_EOK, "ADC enable error");
|
||||
self->is_init = RT_TRUE;
|
||||
}
|
||||
|
||||
return MP_OBJ_FROM_PTR(self);
|
||||
}
|
||||
|
||||
STATIC mp_obj_t machine_adc_init(size_t n_args, const mp_obj_t *args) {
|
||||
machine_adc_obj_t *self = MP_OBJ_TO_PTR(args[0]);
|
||||
rt_err_t result = RT_EOK;
|
||||
|
||||
result = rt_adc_enable(self->adc_device, mp_obj_get_int(args[1]));
|
||||
error_check(result == RT_EOK, "ADC enable error");
|
||||
self->channel = mp_obj_get_int(args[1]);
|
||||
self->is_init = RT_TRUE;
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_adc_init_obj, 2, 2, machine_adc_init);
|
||||
|
||||
STATIC mp_obj_t machine_adc_deinit(mp_obj_t self_in) {
|
||||
machine_adc_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
rt_err_t result = RT_EOK;
|
||||
|
||||
if (self->is_init == RT_TRUE) {
|
||||
result = rt_adc_disable(self->adc_device, self->channel);
|
||||
error_check(result == RT_EOK, "ADC disable error");
|
||||
self->is_init = RT_FALSE;
|
||||
}
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_adc_deinit_obj, machine_adc_deinit);
|
||||
|
||||
STATIC mp_obj_t machine_adc_read(mp_obj_t self_in) {
|
||||
machine_adc_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
int tval = 0;
|
||||
|
||||
error_check(self->is_init == RT_TRUE, "ADC device uninitialized");
|
||||
|
||||
tval = rt_adc_read(self->adc_device, self->channel);
|
||||
return MP_OBJ_NEW_SMALL_INT(tval);
|
||||
}
|
||||
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_adc_read_obj, machine_adc_read);
|
||||
|
||||
STATIC const mp_rom_map_elem_t machine_adc_locals_dict_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_adc_init_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_adc_deinit_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&machine_adc_read_obj) },
|
||||
};
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(machine_adc_locals_dict,
|
||||
machine_adc_locals_dict_table);
|
||||
|
||||
const mp_obj_type_t machine_adc_type = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_ADC,
|
||||
.make_new = machine_adc_make_new,
|
||||
.locals_dict = (mp_obj_dict_t *) &machine_adc_locals_dict,
|
||||
};
|
||||
|
||||
#endif // MICROPYTHON_USING_MACHINE_adc
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2019 ChenYong (chenyong@rt-thread.com)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef MICROPY_INCLUDED_MACHINE_ADC_H
|
||||
#define MICROPY_INCLUDED_MACHINE_ADC_H
|
||||
|
||||
#include "py/obj.h"
|
||||
#include <rtthread.h>
|
||||
|
||||
extern const mp_obj_type_t machine_adc_type;
|
||||
|
||||
#endif // MICROPY_INCLUDED_MACHINE_ADC_H
|
||||
@@ -0,0 +1,361 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 SummerGift <zhangyuan@rt-thread.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <rtdevice.h>
|
||||
|
||||
#include "py/runtime.h"
|
||||
#include "py/mphal.h"
|
||||
#include "py/mperrno.h"
|
||||
#include "extmod/machine_i2c.h"
|
||||
|
||||
#ifdef MICROPYTHON_USING_MACHINE_I2C
|
||||
|
||||
STATIC const mp_obj_type_t machine_hard_i2c_type;
|
||||
|
||||
STATIC const mp_arg_t machine_i2c_mem_allowed_args[] = {
|
||||
{ MP_QSTR_addr, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} },
|
||||
{ MP_QSTR_memaddr, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} },
|
||||
{ MP_QSTR_arg, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
|
||||
{ MP_QSTR_addrsize, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 8} },
|
||||
};
|
||||
|
||||
typedef struct _machine_hard_i2c_obj_t {
|
||||
mp_obj_base_t base;
|
||||
struct rt_i2c_bus_device *i2c_bus;
|
||||
} machine_hard_i2c_obj_t;
|
||||
|
||||
#ifndef RT_USING_I2C
|
||||
#error "Please define the RT_USING_I2C on 'rtconfig.h'"
|
||||
#endif
|
||||
|
||||
STATIC void machine_hard_i2c_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
|
||||
machine_hard_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
mp_printf(print,"I2C(%s, timeout=%u)",
|
||||
self->i2c_bus->parent.parent.name,
|
||||
self->i2c_bus->timeout);
|
||||
return;
|
||||
}
|
||||
|
||||
STATIC int write_mem(mp_obj_t self_in, uint16_t addr, uint32_t memaddr, uint8_t addrsize, const uint8_t *buf, size_t len) {
|
||||
machine_hard_i2c_obj_t *self = (machine_hard_i2c_obj_t*)MP_OBJ_TO_PTR(self_in);
|
||||
|
||||
// Create buffer with memory address
|
||||
size_t memaddr_len = 0;
|
||||
uint8_t memaddr_buf[4];
|
||||
for (int16_t i = addrsize - 8; i >= 0; i -= 8) {
|
||||
memaddr_buf[memaddr_len++] = memaddr >> i;
|
||||
}
|
||||
|
||||
struct rt_i2c_msg msg[2];
|
||||
|
||||
msg[0].buf = memaddr_buf;
|
||||
msg[0].len = (addrsize + 7)/8;
|
||||
msg[0].flags = RT_I2C_WR;
|
||||
msg[0].addr = addr;
|
||||
|
||||
msg[1].buf = (rt_uint8_t*)buf;
|
||||
msg[1].len = len;
|
||||
msg[1].flags = RT_I2C_WR;
|
||||
msg[1].addr = addr;
|
||||
|
||||
if (rt_i2c_transfer(self->i2c_bus, msg, 2) != 2)
|
||||
return -MP_EIO;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
STATIC int read_mem(mp_obj_t self_in, uint16_t addr, uint32_t memaddr, uint8_t addrsize, uint8_t *buf, size_t len) {
|
||||
machine_hard_i2c_obj_t *self = (machine_hard_i2c_obj_t*)MP_OBJ_TO_PTR(self_in);
|
||||
uint8_t memaddr_buf[4];
|
||||
size_t memaddr_len = 0;
|
||||
for (int16_t i = addrsize - 8; i >= 0; i -= 8) {
|
||||
memaddr_buf[memaddr_len++] = memaddr >> i;
|
||||
}
|
||||
|
||||
struct rt_i2c_msg msg[2];
|
||||
|
||||
msg[0].buf = memaddr_buf;
|
||||
msg[0].len = (addrsize + 7)/8;
|
||||
msg[0].flags = RT_I2C_WR;
|
||||
msg[0].addr = addr;
|
||||
|
||||
msg[1].buf = buf;
|
||||
msg[1].len = len;
|
||||
msg[1].flags = RT_I2C_RD;
|
||||
msg[1].addr = addr;
|
||||
|
||||
if (rt_i2c_transfer(self->i2c_bus, msg, 2) != 2)
|
||||
return -MP_EIO;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
STATIC int mp_machine_i2c_readfrom(mp_obj_base_t *self_in, uint16_t addr, uint8_t *dest, size_t len, bool stop) {
|
||||
machine_hard_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
return rt_i2c_master_recv(self->i2c_bus, addr, 0, dest, len);
|
||||
}
|
||||
|
||||
STATIC int mp_machine_i2c_writeto(mp_obj_base_t *self_in, uint16_t addr, const uint8_t *src, size_t len, bool stop) {
|
||||
uint8_t buf[1] = {0};
|
||||
machine_hard_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
if (len == 0){
|
||||
len = 1;
|
||||
if (src == NULL){
|
||||
src = buf;
|
||||
}
|
||||
return !rt_i2c_master_send(self->i2c_bus, addr, 0, src, len);
|
||||
} else if (src == NULL){
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "buf must not NULL"));
|
||||
}
|
||||
return rt_i2c_master_send(self->i2c_bus, addr, 0, src, len);
|
||||
}
|
||||
|
||||
STATIC mp_obj_t machine_i2c_scan(mp_obj_t self_in) {
|
||||
mp_obj_base_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
mp_obj_t list = mp_obj_new_list(0, NULL);
|
||||
// 7-bit addresses 0b0000xxx and 0b1111xxx are reserved
|
||||
for (int addr = 0x08; addr < 0x78; ++addr) {
|
||||
int ret = mp_machine_i2c_writeto(self, addr, NULL, 0, true);
|
||||
if (ret == 0) {
|
||||
mp_obj_list_append(list, MP_OBJ_NEW_SMALL_INT(addr));
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_i2c_scan_obj, machine_i2c_scan);
|
||||
|
||||
STATIC mp_obj_t machine_i2c_readfrom(size_t n_args, const mp_obj_t *args) {
|
||||
mp_obj_base_t *self = (mp_obj_base_t*)MP_OBJ_TO_PTR(args[0]);
|
||||
mp_int_t addr = mp_obj_get_int(args[1]);
|
||||
vstr_t vstr;
|
||||
vstr_init_len(&vstr, mp_obj_get_int(args[2]));
|
||||
bool stop = (n_args == 3) ? true : mp_obj_is_true(args[3]);
|
||||
int ret = mp_machine_i2c_readfrom(self, addr, (uint8_t*)vstr.buf, vstr.len, stop);
|
||||
if (ret < 0) {
|
||||
mp_raise_OSError(-ret);
|
||||
}
|
||||
return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_i2c_readfrom_obj, 3, 4, machine_i2c_readfrom);
|
||||
|
||||
STATIC mp_obj_t machine_i2c_readfrom_into(size_t n_args, const mp_obj_t *args) {
|
||||
mp_obj_base_t *self = (mp_obj_base_t*)MP_OBJ_TO_PTR(args[0]);
|
||||
mp_int_t addr = mp_obj_get_int(args[1]);
|
||||
mp_buffer_info_t bufinfo;
|
||||
mp_get_buffer_raise(args[2], &bufinfo, MP_BUFFER_WRITE);
|
||||
bool stop = (n_args == 3) ? true : mp_obj_is_true(args[3]);
|
||||
int ret = mp_machine_i2c_readfrom(self, addr, bufinfo.buf, bufinfo.len, stop);
|
||||
if (ret < 0) {
|
||||
mp_raise_OSError(-ret);
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_i2c_readfrom_into_obj, 3, 4, machine_i2c_readfrom_into);
|
||||
|
||||
STATIC mp_obj_t machine_i2c_writeto(size_t n_args, const mp_obj_t *args) {
|
||||
mp_obj_base_t *self = (mp_obj_base_t*)MP_OBJ_TO_PTR(args[0]);
|
||||
mp_int_t addr = mp_obj_get_int(args[1]);
|
||||
mp_buffer_info_t bufinfo;
|
||||
mp_get_buffer_raise(args[2], &bufinfo, MP_BUFFER_READ);
|
||||
bool stop = (n_args == 3) ? true : mp_obj_is_true(args[3]);
|
||||
int ret = mp_machine_i2c_writeto(self, addr, bufinfo.buf, bufinfo.len, stop);
|
||||
if (ret < 0) {
|
||||
mp_raise_OSError(-ret);
|
||||
}
|
||||
// return number of acks received
|
||||
return MP_OBJ_NEW_SMALL_INT(ret);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_i2c_writeto_obj, 3, 4, machine_i2c_writeto);
|
||||
|
||||
STATIC mp_obj_t machine_i2c_writevto(size_t n_args, const mp_obj_t *args) {
|
||||
mp_obj_base_t *self = (mp_obj_base_t*)MP_OBJ_TO_PTR(args[0]);
|
||||
mp_int_t addr = mp_obj_get_int(args[1]);
|
||||
|
||||
// Get the list of data buffer(s) to write
|
||||
size_t nitems;
|
||||
const mp_obj_t *items;
|
||||
mp_obj_get_array(args[2], &nitems, (mp_obj_t**)&items);
|
||||
|
||||
// Get the stop argument
|
||||
bool stop = (n_args == 3) ? true : mp_obj_is_true(args[3]);
|
||||
|
||||
// Extract all buffer data, skipping zero-length buffers
|
||||
size_t alloc = nitems == 0 ? 1 : nitems;
|
||||
size_t nbufs = 0;
|
||||
struct rt_i2c_msg *bufs = mp_local_alloc(alloc * sizeof(struct rt_i2c_msg));
|
||||
for (; nitems--; ++items) {
|
||||
mp_buffer_info_t bufinfo;
|
||||
mp_get_buffer_raise(*items, &bufinfo, MP_BUFFER_READ);
|
||||
if (bufinfo.len > 0) {
|
||||
bufs[nbufs].addr = addr;
|
||||
bufs[nbufs].flags = RT_I2C_WR;
|
||||
bufs[nbufs].len = bufinfo.len;
|
||||
bufs[nbufs++].buf = bufinfo.buf;
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure there is at least one buffer, empty if needed
|
||||
if (nbufs == 0) {
|
||||
bufs[0].len = 0;
|
||||
bufs[0].buf = NULL;
|
||||
nbufs = 1;
|
||||
}
|
||||
|
||||
// Do the I2C transfer
|
||||
machine_hard_i2c_obj_t *i2c_p = (machine_hard_i2c_obj_t*)self;
|
||||
int ret = rt_i2c_transfer(i2c_p->i2c_bus, bufs, nbufs);
|
||||
mp_local_free(bufs);
|
||||
|
||||
if (ret < 0) {
|
||||
mp_raise_OSError(-ret);
|
||||
}
|
||||
|
||||
// Return number of acks received
|
||||
return MP_OBJ_NEW_SMALL_INT(ret);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_i2c_writevto_obj, 3, 4, machine_i2c_writevto);
|
||||
|
||||
STATIC mp_obj_t machine_i2c_readfrom_mem(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
enum { ARG_addr, ARG_memaddr, ARG_n, ARG_addrsize };
|
||||
mp_arg_val_t args[MP_ARRAY_SIZE(machine_i2c_mem_allowed_args)];
|
||||
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args,
|
||||
MP_ARRAY_SIZE(machine_i2c_mem_allowed_args), machine_i2c_mem_allowed_args, args);
|
||||
|
||||
// create the buffer to store data into
|
||||
vstr_t vstr;
|
||||
vstr_init_len(&vstr, mp_obj_get_int(args[ARG_n].u_obj));
|
||||
|
||||
// do the transfer
|
||||
int ret = read_mem(pos_args[0], args[ARG_addr].u_int, args[ARG_memaddr].u_int,
|
||||
args[ARG_addrsize].u_int, (uint8_t*)vstr.buf, vstr.len);
|
||||
if (ret < 0) {
|
||||
mp_raise_OSError(-ret);
|
||||
}
|
||||
|
||||
return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_i2c_readfrom_mem_obj, 1, machine_i2c_readfrom_mem);
|
||||
|
||||
STATIC mp_obj_t machine_i2c_readfrom_mem_into(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
enum { ARG_addr, ARG_memaddr, ARG_buf, ARG_addrsize };
|
||||
mp_arg_val_t args[MP_ARRAY_SIZE(machine_i2c_mem_allowed_args)];
|
||||
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args,
|
||||
MP_ARRAY_SIZE(machine_i2c_mem_allowed_args), machine_i2c_mem_allowed_args, args);
|
||||
|
||||
// get the buffer to store data into
|
||||
mp_buffer_info_t bufinfo;
|
||||
mp_get_buffer_raise(args[ARG_buf].u_obj, &bufinfo, MP_BUFFER_WRITE);
|
||||
|
||||
// do the transfer
|
||||
int ret = read_mem(pos_args[0], args[ARG_addr].u_int, args[ARG_memaddr].u_int,
|
||||
args[ARG_addrsize].u_int, bufinfo.buf, bufinfo.len);
|
||||
if (ret < 0) {
|
||||
mp_raise_OSError(-ret);
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_i2c_readfrom_mem_into_obj, 1, machine_i2c_readfrom_mem_into);
|
||||
|
||||
STATIC mp_obj_t machine_i2c_writeto_mem(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
enum { ARG_addr, ARG_memaddr, ARG_buf, ARG_addrsize };
|
||||
mp_arg_val_t args[MP_ARRAY_SIZE(machine_i2c_mem_allowed_args)];
|
||||
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args,
|
||||
MP_ARRAY_SIZE(machine_i2c_mem_allowed_args), machine_i2c_mem_allowed_args, args);
|
||||
|
||||
// get the buffer to write the data from
|
||||
mp_buffer_info_t bufinfo;
|
||||
mp_get_buffer_raise(args[ARG_buf].u_obj, &bufinfo, MP_BUFFER_READ);
|
||||
|
||||
// do the transfer
|
||||
int ret = write_mem(pos_args[0], args[ARG_addr].u_int, args[ARG_memaddr].u_int,
|
||||
args[ARG_addrsize].u_int, bufinfo.buf, bufinfo.len);
|
||||
if (ret < 0) {
|
||||
mp_raise_OSError(-ret);
|
||||
}
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_i2c_writeto_mem_obj, 1, machine_i2c_writeto_mem);
|
||||
|
||||
STATIC const mp_rom_map_elem_t machine_i2c_locals_dict_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR_scan), MP_ROM_PTR(&machine_i2c_scan_obj) },
|
||||
|
||||
// standard bus operations
|
||||
{ MP_ROM_QSTR(MP_QSTR_readfrom), MP_ROM_PTR(&machine_i2c_readfrom_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_readfrom_into), MP_ROM_PTR(&machine_i2c_readfrom_into_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_writeto), MP_ROM_PTR(&machine_i2c_writeto_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_writevto), MP_ROM_PTR(&machine_i2c_writevto_obj) },
|
||||
|
||||
// memory operations
|
||||
{ MP_ROM_QSTR(MP_QSTR_readfrom_mem), MP_ROM_PTR(&machine_i2c_readfrom_mem_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_readfrom_mem_into), MP_ROM_PTR(&machine_i2c_readfrom_mem_into_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_writeto_mem), MP_ROM_PTR(&machine_i2c_writeto_mem_obj) },
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
/* MicroPython bindings for machine API */
|
||||
|
||||
mp_obj_t machine_hard_i2c_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
|
||||
char iic_device[RT_NAME_MAX];
|
||||
|
||||
snprintf(iic_device, sizeof(iic_device), "i2c%d", mp_obj_get_int(all_args[0]));
|
||||
struct rt_i2c_bus_device *i2c_bus = rt_i2c_bus_device_find(iic_device);
|
||||
|
||||
if (i2c_bus == RT_NULL) {
|
||||
mp_printf(&mp_plat_print, "can't find %s device\r\n", iic_device);
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "I2C(%s) doesn't exist", iic_device));
|
||||
}
|
||||
|
||||
// create new hard I2C object
|
||||
machine_hard_i2c_obj_t *self = m_new_obj(machine_hard_i2c_obj_t);
|
||||
self->base.type = &machine_hard_i2c_type;
|
||||
self->i2c_bus = i2c_bus;
|
||||
return (mp_obj_t) self;
|
||||
}
|
||||
|
||||
MP_DEFINE_CONST_DICT(mp_machine_hard_i2c_locals_dict, machine_i2c_locals_dict_table);
|
||||
|
||||
STATIC const mp_machine_i2c_p_t machine_hard_i2c_p = {
|
||||
.start = NULL,
|
||||
.stop = NULL,
|
||||
.read = NULL,
|
||||
.write = NULL,
|
||||
.transfer = NULL,
|
||||
.transfer_single = NULL,
|
||||
};
|
||||
|
||||
STATIC const mp_obj_type_t machine_hard_i2c_type = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_I2C,
|
||||
.print = machine_hard_i2c_print,
|
||||
.make_new = machine_hard_i2c_make_new,
|
||||
.protocol = &machine_hard_i2c_p,
|
||||
.locals_dict = (mp_obj_dict_t*)&mp_machine_hard_i2c_locals_dict,
|
||||
};
|
||||
|
||||
#endif // MICROPYTHON_USING_MACHINE_I2C
|
||||
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018 SummerGift <zhangyuan@rt-thread.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <rtdevice.h>
|
||||
|
||||
#include "py/runtime.h"
|
||||
#include "py/mphal.h"
|
||||
#include "extmod/machine_spi.h"
|
||||
|
||||
#ifdef MICROPYTHON_USING_MACHINE_SPI
|
||||
|
||||
#ifndef RT_USING_SPI
|
||||
#error "Please define the RT_USING_SPI on 'rtconfig.h'"
|
||||
#endif
|
||||
|
||||
STATIC const mp_obj_type_t machine_hard_spi_type;
|
||||
|
||||
typedef struct _machine_hard_spi_obj_t {
|
||||
mp_obj_base_t base;
|
||||
struct rt_spi_device *spi_device;
|
||||
} machine_hard_spi_obj_t;
|
||||
|
||||
STATIC void machine_hard_spi_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
|
||||
machine_hard_spi_obj_t *self = (machine_hard_spi_obj_t*)self_in;
|
||||
mp_printf(print,"SPI(device port : %s)",self->spi_device->parent.parent.name);
|
||||
}
|
||||
|
||||
mp_obj_t machine_hard_spi_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
|
||||
char spi_dev_name[RT_NAME_MAX];
|
||||
|
||||
snprintf(spi_dev_name, sizeof(spi_dev_name), "spi%d", mp_obj_get_int(all_args[0]));
|
||||
|
||||
struct rt_spi_device *rt_spi_device = (struct rt_spi_device *) rt_device_find(spi_dev_name);
|
||||
if (rt_spi_device == RT_NULL || rt_spi_device->parent.type != RT_Device_Class_SPIDevice) {
|
||||
mp_printf(&mp_plat_print, "ERROR: SPI device %s not found!\n", spi_dev_name);
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "SPI(%s) doesn't exist", spi_dev_name));
|
||||
}
|
||||
|
||||
// create new hard SPI object
|
||||
machine_hard_spi_obj_t *self = m_new_obj(machine_hard_spi_obj_t);
|
||||
self->base.type = &machine_hard_spi_type;
|
||||
self->spi_device = rt_spi_device;
|
||||
return (mp_obj_t) self;
|
||||
}
|
||||
|
||||
//SPI.init( baudrate=100000, polarity=0, phase=0, bits=8, firstbit=SPI.MSB/LSB )
|
||||
STATIC void machine_hard_spi_init(mp_obj_base_t *self_in, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
machine_hard_spi_obj_t *self = (machine_hard_spi_obj_t*)self_in;
|
||||
rt_uint8_t mode = 0;
|
||||
int baudrate = mp_obj_get_int(pos_args[0]);
|
||||
int polarity = mp_obj_get_int(pos_args[1]);
|
||||
int phase = mp_obj_get_int(pos_args[2]);
|
||||
int bits = mp_obj_get_int(pos_args[3]);
|
||||
int firstbit = mp_obj_get_int(pos_args[4]);
|
||||
|
||||
if(!polarity && !phase)
|
||||
{
|
||||
mode = RT_SPI_MODE_0;
|
||||
}
|
||||
|
||||
if(!polarity && phase)
|
||||
{
|
||||
mode = RT_SPI_MODE_1;
|
||||
}
|
||||
|
||||
if(polarity && !phase)
|
||||
{
|
||||
mode = RT_SPI_MODE_2;
|
||||
}
|
||||
|
||||
if(polarity && phase)
|
||||
{
|
||||
mode = RT_SPI_MODE_3;
|
||||
}
|
||||
|
||||
if(firstbit)
|
||||
{
|
||||
mode |= RT_SPI_MSB;
|
||||
} else {
|
||||
mode |= RT_SPI_LSB;
|
||||
}
|
||||
|
||||
/* config spi */
|
||||
{
|
||||
struct rt_spi_configuration cfg;
|
||||
cfg.data_width = bits;
|
||||
cfg.mode = mode;
|
||||
cfg.max_hz = baudrate;
|
||||
rt_spi_configure(self->spi_device, &cfg);
|
||||
}
|
||||
}
|
||||
|
||||
STATIC void machine_hard_spi_transfer(mp_obj_base_t *self_in, size_t len, const uint8_t *src, uint8_t *dest) {
|
||||
machine_hard_spi_obj_t *self = (machine_hard_spi_obj_t*)self_in;
|
||||
|
||||
if (src && dest) {
|
||||
rt_spi_send_then_recv(self->spi_device, src, len, dest, len);
|
||||
} else if (src) {
|
||||
rt_spi_send(self->spi_device, src, len);
|
||||
} else {
|
||||
rt_spi_recv(self->spi_device, dest, len);
|
||||
}
|
||||
}
|
||||
|
||||
STATIC const mp_machine_spi_p_t machine_hard_spi_p = {
|
||||
.init = machine_hard_spi_init,
|
||||
.deinit = NULL,
|
||||
.transfer = machine_hard_spi_transfer,
|
||||
};
|
||||
|
||||
STATIC const mp_obj_type_t machine_hard_spi_type = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_SPI,
|
||||
.print = machine_hard_spi_print,
|
||||
.make_new = machine_hard_spi_make_new,
|
||||
.protocol = &machine_hard_spi_p,
|
||||
.locals_dict = (mp_obj_t)&mp_machine_spi_locals_dict,
|
||||
};
|
||||
|
||||
#endif // MICROPYTHON_USING_MACHINE_SPI
|
||||
|
||||
@@ -0,0 +1,356 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2019 SummerGift <SummerGift@qq.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "py/mphal.h"
|
||||
#include "py/runtime.h"
|
||||
#include "py/mperrno.h"
|
||||
|
||||
#if MICROPY_PY_MACHINE_LCD
|
||||
#include <dfs_posix.h>
|
||||
#include "machine_lcd.h"
|
||||
#include <drv_lcd.h>
|
||||
|
||||
#define MAX_CO (2400 - 1)
|
||||
|
||||
typedef struct _machine_lcd_obj_t {
|
||||
mp_obj_base_t base;
|
||||
} machine_lcd_obj_t;
|
||||
|
||||
STATIC void error_check(bool status, const char *msg) {
|
||||
if (!status) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, msg));
|
||||
}
|
||||
}
|
||||
|
||||
/// \classmethod \constructor(skin_position)
|
||||
///
|
||||
/// Construct an LCD object.
|
||||
STATIC mp_obj_t machine_lcd_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
|
||||
// check arguments
|
||||
mp_arg_check_num(n_args, n_kw, 0, 0, false);
|
||||
|
||||
// create lcd object
|
||||
machine_lcd_obj_t *lcd = m_new_obj(machine_lcd_obj_t);
|
||||
lcd->base.type = &machine_lcd_type;
|
||||
|
||||
return MP_OBJ_FROM_PTR(lcd);
|
||||
}
|
||||
|
||||
/// \method light(value)
|
||||
///
|
||||
/// Turn the backlight on/off. True or 1 turns it on, False or 0 turns it off.
|
||||
STATIC mp_obj_t machine_lcd_light(mp_obj_t self_in, mp_obj_t value) {
|
||||
if (mp_obj_is_true(value)) {
|
||||
lcd_display_on(); // set pin high to turn backlight on
|
||||
} else {
|
||||
lcd_display_off();// set pin low to turn backlight off
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(machine_lcd_light_obj, machine_lcd_light);
|
||||
|
||||
/// \method fill(colour)
|
||||
///
|
||||
/// Fill the screen with the given colour.
|
||||
///
|
||||
STATIC mp_obj_t machine_lcd_fill(mp_obj_t self_in, mp_obj_t col_in) {
|
||||
int col = mp_obj_get_int(col_in);
|
||||
lcd_clear(col);
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(machine_lcd_fill_obj, machine_lcd_fill);
|
||||
|
||||
/// \method pixel(x, y, colour)
|
||||
///
|
||||
/// Set the pixel at `(x, y)` to the given colour.
|
||||
///
|
||||
STATIC mp_obj_t machine_lcd_pixel(size_t n_args, const mp_obj_t *args) {
|
||||
int x = mp_obj_get_int(args[1]);
|
||||
int y = mp_obj_get_int(args[2]);
|
||||
|
||||
error_check((x >= 0 && x <= MAX_CO) && (y >= 0 && y <= MAX_CO) , "The min/max X/Y coordinates is 0/239");
|
||||
|
||||
int col = mp_obj_get_int(args[3]);
|
||||
lcd_draw_point_color(x, y, col);
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_lcd_pixel_obj, 4, 4, machine_lcd_pixel);
|
||||
|
||||
/// \method text(str, x, y, size)
|
||||
///
|
||||
/// Draw the given text to the position `(x, y)` using the given size (16 24 32).
|
||||
///
|
||||
STATIC mp_obj_t machine_lcd_text(size_t n_args, const mp_obj_t *args) {
|
||||
size_t len;
|
||||
const char *data = mp_obj_str_get_data(args[1], &len);
|
||||
int x = mp_obj_get_int(args[2]);
|
||||
int y = mp_obj_get_int(args[3]);
|
||||
int size = mp_obj_get_int(args[4]);
|
||||
|
||||
error_check((x >= 0 && x <= MAX_CO) && (y >= 0 && y <= MAX_CO) , "The min/max X/Y coordinates is 0/239");
|
||||
|
||||
error_check(size == 16 || size == 24 || size == 32, "lcd only support font size 16 24 32");
|
||||
|
||||
lcd_show_string(x, y, size, data);
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_lcd_text_obj, 5, 5, machine_lcd_text);
|
||||
|
||||
/// \method line(x1, y1, x2, y2)
|
||||
///
|
||||
/// display a line on the lcd, from (x1, y1) to (x2, y2).
|
||||
///
|
||||
STATIC mp_obj_t machine_lcd_line(size_t n_args, const mp_obj_t *args) {
|
||||
int x1 = mp_obj_get_int(args[1]);
|
||||
int y1 = mp_obj_get_int(args[2]);
|
||||
int x2 = mp_obj_get_int(args[3]);
|
||||
int y2 = mp_obj_get_int(args[4]);
|
||||
|
||||
error_check((x1 >= 0 && x1 <= MAX_CO) && (y1 >= 0 && y1 <= MAX_CO) , "The min/max X/Y coordinates is 0/239");
|
||||
error_check((x2 >= 0 && x2 <= MAX_CO) && (y2 >= 0 && y2 <= MAX_CO) , "The min/max X/Y coordinates is 0/239");
|
||||
|
||||
lcd_draw_line(x1, y1, x2, y2);
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_lcd_line_obj, 5, 5, machine_lcd_line);
|
||||
|
||||
/// \method rectangle(x1, y1, x2, y2)
|
||||
///
|
||||
/// display a rectangle on the lcd, from (x1, y1) to (x2, y2).
|
||||
///
|
||||
STATIC mp_obj_t machine_lcd_rectangle(size_t n_args, const mp_obj_t *args) {
|
||||
int x1 = mp_obj_get_int(args[1]);
|
||||
int y1 = mp_obj_get_int(args[2]);
|
||||
int x2 = mp_obj_get_int(args[3]);
|
||||
int y2 = mp_obj_get_int(args[4]);
|
||||
|
||||
error_check((x1 >= 0 && x1 <= MAX_CO) && (y1 >= 0 && y1 <= MAX_CO) , "The min/max X/Y coordinates is 0/239");
|
||||
error_check((x2 >= 0 && x2 <= MAX_CO) && (y2 >= 0 && y2 <= MAX_CO) , "The min/max X/Y coordinates is 0/239");
|
||||
|
||||
lcd_draw_rectangle(x1, y1, x2, y2);
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_lcd_rectangle_obj, 5, 5, machine_lcd_rectangle);
|
||||
|
||||
/// \method circle(x1, y1, r)
|
||||
///
|
||||
/// display a circle on the lcd, center(x1, y1) R = r.
|
||||
///
|
||||
STATIC mp_obj_t machine_lcd_circle(size_t n_args, const mp_obj_t *args) {
|
||||
int x1 = mp_obj_get_int(args[1]);
|
||||
int y1 = mp_obj_get_int(args[2]);
|
||||
int r = mp_obj_get_int(args[3]);
|
||||
|
||||
error_check((x1 >= 0 && x1 <= MAX_CO) && (y1 >= 0 && y1 <= MAX_CO) , "The min/max X/Y coordinates is 0/239");
|
||||
|
||||
lcd_draw_circle(x1, y1, r);
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_lcd_circle_obj, 4, 4, machine_lcd_circle);
|
||||
|
||||
/// \method set_color(back, fore)
|
||||
///
|
||||
/// Set background color and foreground color.
|
||||
///
|
||||
STATIC mp_obj_t machine_lcd_set_color(size_t n_args, const mp_obj_t *args) {
|
||||
rt_uint16_t back = mp_obj_get_int(args[1]);
|
||||
rt_uint16_t fore = mp_obj_get_int(args[2]);
|
||||
|
||||
lcd_set_color(back, fore);
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_lcd_set_color_obj, 3, 3, machine_lcd_set_color);
|
||||
|
||||
/// \method show_image array
|
||||
///
|
||||
/// display the image on the lcd..
|
||||
/// @param x x position
|
||||
/// @param y y position
|
||||
/// @param length length of image
|
||||
/// @param wide wide of image
|
||||
/// @param p image_array
|
||||
STATIC mp_obj_t machine_lcd_show_image(size_t n_args, const mp_obj_t *args) {
|
||||
rt_uint16_t x = mp_obj_get_int(args[1]);
|
||||
rt_uint16_t y = mp_obj_get_int(args[2]);
|
||||
rt_uint16_t length = mp_obj_get_int(args[3]);
|
||||
rt_uint16_t wide = mp_obj_get_int(args[4]);
|
||||
|
||||
mp_buffer_info_t bufinfo;
|
||||
if (mp_get_buffer(args[5], &bufinfo, MP_BUFFER_READ))
|
||||
{
|
||||
lcd_show_image( x, y, length, wide, (const rt_uint8_t *)bufinfo.buf);
|
||||
}
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_lcd_show_image_obj, 6, 6, machine_lcd_show_image);
|
||||
|
||||
STATIC rt_uint16_t rgb888to565(rt_uint32_t RGB)
|
||||
{
|
||||
int R, G, B;
|
||||
R = (RGB >> 19) & 0x1F;
|
||||
G = (RGB >> 10) & 0x3F;
|
||||
B = (RGB >> 3) & 0x1F;
|
||||
return (R << 11) | (G << 5) | B;
|
||||
}
|
||||
|
||||
/// \method show_image array
|
||||
///
|
||||
/// display the image on the lcd.
|
||||
/// @param x x position
|
||||
/// @param y y position
|
||||
/// @param file bmp file pathname
|
||||
STATIC mp_obj_t machine_lcd_show_bmp(size_t n_args, const mp_obj_t *args) {
|
||||
#define BMP_INFO_SIZE 54
|
||||
rt_uint16_t x = mp_obj_get_int(args[1]);
|
||||
rt_uint16_t y = mp_obj_get_int(args[2]);
|
||||
const char *pathname = mp_obj_str_get_str(args[3]);
|
||||
|
||||
int fd, len;
|
||||
fd = open(pathname, O_RDONLY, 0);
|
||||
if (fd < 0)
|
||||
{
|
||||
mp_raise_OSError(MP_EINVAL);
|
||||
}
|
||||
|
||||
void *bmp_info = rt_malloc(BMP_INFO_SIZE);
|
||||
if (bmp_info == RT_NULL)
|
||||
{
|
||||
mp_raise_OSError(MP_ENOMEM);
|
||||
}
|
||||
|
||||
len = read(fd, bmp_info, BMP_INFO_SIZE);
|
||||
if (len < 0)
|
||||
{
|
||||
close(fd);
|
||||
mp_raise_OSError(MP_EINVAL);
|
||||
}
|
||||
|
||||
rt_uint32_t width = *(rt_uint32_t *)(bmp_info + 18);
|
||||
rt_uint32_t heigth = *(rt_uint32_t *)(bmp_info + 22);
|
||||
rt_uint16_t bit_count = *(rt_uint16_t *)(bmp_info + 28);
|
||||
|
||||
if (bit_count != 32)
|
||||
{
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError,
|
||||
"bit count : %d, only support 32-bit bmp picture", bit_count));
|
||||
}
|
||||
|
||||
void *image_buf = rt_malloc(2 * width);
|
||||
if (image_buf == RT_NULL)
|
||||
{
|
||||
mp_raise_OSError(MP_ENOMEM);
|
||||
}
|
||||
|
||||
void *row_buf = rt_malloc(4 * width);
|
||||
if (row_buf == RT_NULL)
|
||||
{
|
||||
mp_raise_OSError(MP_ENOMEM);
|
||||
}
|
||||
|
||||
int image_index, row_index;
|
||||
rt_uint16_t rgb565_temp;
|
||||
|
||||
for(int i = 0; i < heigth; i++)
|
||||
{
|
||||
image_index = 0;
|
||||
row_index = 0;
|
||||
|
||||
len = read(fd, row_buf, 4 * width);
|
||||
if (len < 0)
|
||||
{
|
||||
close(fd);
|
||||
mp_raise_OSError(MP_EINVAL);
|
||||
}
|
||||
|
||||
while(row_index < (4 * width))
|
||||
{
|
||||
rgb565_temp = rgb888to565(*(rt_uint32_t *)(row_buf + row_index));
|
||||
*(rt_uint8_t *)(image_buf + image_index) = (rgb565_temp >> 8);
|
||||
*(rt_uint8_t *)(image_buf + image_index + 1) = rgb565_temp & 0xff;
|
||||
|
||||
row_index += 4;
|
||||
image_index += 2;
|
||||
}
|
||||
|
||||
lcd_show_image( x, y--, width, 1, (const rt_uint8_t *)image_buf);
|
||||
}
|
||||
|
||||
close(fd);
|
||||
rt_free(bmp_info);
|
||||
rt_free(image_buf);
|
||||
rt_free(row_buf);
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_lcd_show_bmp_obj, 4, 4, machine_lcd_show_bmp);
|
||||
|
||||
STATIC const mp_rom_map_elem_t machine_lcd_locals_dict_table[] = {
|
||||
// instance methods
|
||||
{ MP_ROM_QSTR(MP_QSTR_light), MP_ROM_PTR(&machine_lcd_light_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_fill), MP_ROM_PTR(&machine_lcd_fill_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_pixel), MP_ROM_PTR(&machine_lcd_pixel_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_text), MP_ROM_PTR(&machine_lcd_text_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_line), MP_ROM_PTR(&machine_lcd_line_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_rectangle), MP_ROM_PTR(&machine_lcd_rectangle_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_circle), MP_ROM_PTR(&machine_lcd_circle_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_set_color), MP_ROM_PTR(&machine_lcd_set_color_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_show_image), MP_ROM_PTR(&machine_lcd_show_image_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_show_bmp), MP_ROM_PTR(&machine_lcd_show_bmp_obj) },
|
||||
// color
|
||||
{ MP_ROM_QSTR(MP_QSTR_WHITE), MP_ROM_INT(WHITE) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_BLACK), MP_ROM_INT(BLACK) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_BLUE), MP_ROM_INT(BLUE) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_BRED), MP_ROM_INT(BRED) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_GRED), MP_ROM_INT(GRED) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_GBLUE), MP_ROM_INT(GBLUE) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_RED), MP_ROM_INT(RED) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_MAGENTA), MP_ROM_INT(MAGENTA) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_GREEN), MP_ROM_INT(GREEN) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_CYAN), MP_ROM_INT(CYAN) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_YELLOW), MP_ROM_INT(YELLOW) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_BROWN), MP_ROM_INT(BROWN) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_BRRED), MP_ROM_INT(BRRED) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_GRAY), MP_ROM_INT(GRAY) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_GRAY175), MP_ROM_INT(GRAY175) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_GRAY151), MP_ROM_INT(GRAY151) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_GRAY187), MP_ROM_INT(GRAY187) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_GRAY240), MP_ROM_INT(GRAY240) },
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(machine_lcd_locals_dict, machine_lcd_locals_dict_table);
|
||||
|
||||
const mp_obj_type_t machine_lcd_type = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_LCD,
|
||||
.make_new = machine_lcd_make_new,
|
||||
.locals_dict = (mp_obj_dict_t*)&machine_lcd_locals_dict,
|
||||
};
|
||||
|
||||
#endif // MICROPY_PY_MACHINE_LCD
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2019 SummerGift <SummerGift@qq.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#ifndef MICROPY_INCLUDED_MACHINE_LCD_H
|
||||
#define MICROPY_INCLUDED_MACHINE_LCD_H
|
||||
|
||||
extern const mp_obj_type_t machine_lcd_type;
|
||||
|
||||
#endif // MICROPY_INCLUDED_MACHINE_LCD_H
|
||||
@@ -0,0 +1,298 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Armink (armink.ztl@gmail.com)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <rtthread.h>
|
||||
#include <drivers/pin.h>
|
||||
#include "py/runtime.h"
|
||||
#include "py/gc.h"
|
||||
#include "py/mphal.h"
|
||||
#include "py/mperrno.h"
|
||||
#include "py/stream.h"
|
||||
#include "modmachine.h"
|
||||
|
||||
#if MICROPY_PY_PIN
|
||||
|
||||
#define GPIO_MODE_IN ((uint32_t)0x00000000) /*!< Input Floating Mode */
|
||||
#define GPIO_MODE_OUT_PP ((uint32_t)0x00000001) /*!< Output Push Pull Mode */
|
||||
#define GPIO_MODE_OUT_OD ((uint32_t)0x00000011) /*!< Output Open Drain Mode */
|
||||
#define GPIO_MODE_AF_PP ((uint32_t)0x00000002) /*!< Alternate Function Push Pull Mode */
|
||||
#define GPIO_MODE_AF_OD ((uint32_t)0x00000012) /*!< Alternate Function Open Drain Mode */
|
||||
#define GPIO_MODE_ANALOG ((uint32_t)0x00000003) /*!< Analog Mode */
|
||||
#define GPIO_NOPULL ((uint32_t)0x00000000) /*!< No Pull-up or Pull-down activation */
|
||||
#define GPIO_PULLUP ((uint32_t)0x00000001) /*!< Pull-up activation */
|
||||
#define GPIO_PULLDOWN ((uint32_t)0x00000002) /*!< Pull-down activation */
|
||||
#define GPIO_MODE_IT_RISING ((uint32_t)0x10110000) /*!< External Interrupt Mode with Rising edge trigger detection */
|
||||
#define GPIO_MODE_IT_FALLING ((uint32_t)0x10210000) /*!< External Interrupt Mode with Falling edge trigger detection */
|
||||
#define GPIO_MODE_IT_RISING_FALLING ((uint32_t)0x10310000) /*!< External Interrupt Mode with Rising/Falling edge trigger detection */
|
||||
|
||||
const mp_obj_base_t machine_pin_obj_template = {&machine_pin_type};
|
||||
|
||||
void mp_pin_od_write(void *machine_pin, int stat) {
|
||||
if (stat == PIN_LOW) {
|
||||
rt_pin_mode(((machine_pin_obj_t *)machine_pin)->pin, PIN_MODE_OUTPUT);
|
||||
rt_pin_write(((machine_pin_obj_t *)machine_pin)->pin, stat);
|
||||
} else {
|
||||
rt_pin_mode(((machine_pin_obj_t *)machine_pin)->pin, PIN_MODE_INPUT_PULLUP);
|
||||
}
|
||||
}
|
||||
|
||||
void mp_hal_pin_open_set(void *machine_pin, int mode) {
|
||||
rt_pin_mode(((machine_pin_obj_t *)machine_pin)->pin, mode);
|
||||
}
|
||||
|
||||
char* mp_hal_pin_get_name(void *machine_pin) {
|
||||
return ((machine_pin_obj_t *)machine_pin)->name;
|
||||
}
|
||||
|
||||
STATIC mp_obj_t machine_pin_obj_init_helper(machine_pin_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args);
|
||||
|
||||
STATIC void machine_pin_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
|
||||
machine_pin_obj_t *self = self_in;
|
||||
mp_printf(print, "<Pin %d>", self->pin);
|
||||
}
|
||||
|
||||
// constructor(drv_name, pin, ...)
|
||||
mp_obj_t mp_pin_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
|
||||
mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true);
|
||||
|
||||
// get the wanted port
|
||||
if (!MP_OBJ_IS_TYPE(args[0], &mp_type_tuple)) {
|
||||
mp_raise_ValueError("Pin id must be tuple of (\"GPIO_x\", pin#)");
|
||||
}
|
||||
mp_obj_t *items;
|
||||
mp_obj_get_array_fixed_n(args[0], 2, &items);
|
||||
const char *pin_name = mp_obj_str_get_str(items[0]);
|
||||
int wanted_pin = mp_obj_get_int(items[1]);
|
||||
|
||||
machine_pin_obj_t *pin = m_new_obj(machine_pin_obj_t);
|
||||
if (!pin) {
|
||||
mp_raise_OSError(MP_ENOMEM);
|
||||
}
|
||||
|
||||
strncpy(pin->name, pin_name, sizeof(pin->name));
|
||||
pin->base = machine_pin_obj_template;
|
||||
pin->pin = wanted_pin;
|
||||
|
||||
if (n_args > 1 || n_kw > 0) {
|
||||
// pin mode given, so configure this GPIO
|
||||
mp_map_t kw_args;
|
||||
mp_map_init_fixed_table(&kw_args, n_kw, args + n_args);
|
||||
machine_pin_obj_init_helper(pin, n_args - 1, args + 1, &kw_args);
|
||||
}
|
||||
|
||||
return (mp_obj_t)pin;
|
||||
}
|
||||
|
||||
// pin.init(mode, pull=None, *, value)
|
||||
STATIC mp_obj_t machine_pin_obj_init_helper(machine_pin_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
enum { ARG_mode, ARG_pull, ARG_value };
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{ MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT },
|
||||
{ MP_QSTR_pull, MP_ARG_OBJ, {.u_obj = mp_const_none}},
|
||||
{ MP_QSTR_value, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL}},
|
||||
};
|
||||
|
||||
// parse args
|
||||
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
|
||||
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
|
||||
|
||||
// get io mode
|
||||
uint mode = args[ARG_mode].u_int;
|
||||
|
||||
// get pull mode
|
||||
uint pull = GPIO_NOPULL;
|
||||
|
||||
if (args[ARG_pull].u_obj != mp_const_none) {
|
||||
pull = mp_obj_get_int(args[ARG_pull].u_obj);
|
||||
}
|
||||
|
||||
switch(mode) {
|
||||
case GPIO_MODE_IN: {
|
||||
if (pull == GPIO_PULLUP) {
|
||||
mode = PIN_MODE_INPUT_PULLUP;
|
||||
} else if (pull == GPIO_PULLDOWN) {
|
||||
mode = PIN_MODE_INPUT_PULLDOWN;
|
||||
} else {
|
||||
mode = PIN_MODE_INPUT;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case GPIO_MODE_OUT_PP : {
|
||||
mode = PIN_MODE_OUTPUT;
|
||||
break;
|
||||
}
|
||||
case GPIO_MODE_OUT_OD : {
|
||||
mode = PIN_MODE_OUTPUT_OD;
|
||||
break;
|
||||
}
|
||||
case GPIO_MODE_AF_PP :
|
||||
case GPIO_MODE_AF_OD :
|
||||
case GPIO_MODE_ANALOG :
|
||||
//TODO
|
||||
mp_raise_NotImplementedError("not implemented pin mode");
|
||||
}
|
||||
|
||||
rt_pin_mode(self->pin, mode);
|
||||
|
||||
// get initial value
|
||||
if (args[ARG_value].u_obj != MP_OBJ_NULL) {
|
||||
rt_pin_write(self->pin, mp_obj_is_true(args[ARG_value].u_obj));
|
||||
}
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
// fast method for getting/setting pin value
|
||||
STATIC mp_obj_t machine_pin_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {
|
||||
mp_arg_check_num(n_args, n_kw, 0, 1, false);
|
||||
machine_pin_obj_t *self = self_in;
|
||||
if (n_args == 0) {
|
||||
return mp_obj_new_bool(rt_pin_read(self->pin));
|
||||
} else {
|
||||
rt_pin_write(self->pin, mp_obj_is_true(args[0]));
|
||||
return mp_const_none;
|
||||
}
|
||||
}
|
||||
|
||||
// pin.init(mode, pull)
|
||||
STATIC mp_obj_t machine_pin_obj_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
|
||||
return machine_pin_obj_init_helper(args[0], n_args - 1, args + 1, kw_args);
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_KW(machine_pin_init_obj, 1, machine_pin_obj_init);
|
||||
|
||||
// pin.value([value])
|
||||
STATIC mp_obj_t machine_pin_value(size_t n_args, const mp_obj_t *args) {
|
||||
return machine_pin_call(args[0], n_args - 1, 0, args + 1);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_pin_value_obj, 1, 2, machine_pin_value);
|
||||
|
||||
// pin.name()
|
||||
STATIC mp_obj_t machine_pin_name(size_t n_args, const mp_obj_t *args) {
|
||||
machine_pin_obj_t *self = (machine_pin_obj_t *)args[0];
|
||||
return mp_obj_new_str(self->name, strlen(self->name));
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_pin_name_obj, 1, 2, machine_pin_name);
|
||||
|
||||
// pin.pin()
|
||||
STATIC mp_obj_t machine_pin_pin(size_t n_args, const mp_obj_t *args) {
|
||||
return MP_OBJ_NEW_SMALL_INT(((machine_pin_obj_t *)args[0])->pin);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_pin_pin_obj, 1, 2, machine_pin_pin);
|
||||
|
||||
STATIC mp_uint_t machine_pin_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int *errcode) {
|
||||
(void)errcode;
|
||||
machine_pin_obj_t *self = self_in;
|
||||
|
||||
switch (request) {
|
||||
case MP_PIN_READ: {
|
||||
uint32_t pin_val = rt_pin_read(self->pin);
|
||||
return pin_val;
|
||||
}
|
||||
case MP_PIN_WRITE: {
|
||||
rt_pin_write(self->pin, arg);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
*errcode = MP_EINVAL;
|
||||
return MP_STREAM_ERROR;
|
||||
}
|
||||
|
||||
STATIC void machine_pin_isr_handler(void *arg) {
|
||||
machine_pin_obj_t *self = arg;
|
||||
mp_sched_schedule(self->pin_isr_cb, MP_OBJ_FROM_PTR(self));
|
||||
}
|
||||
|
||||
// pin.irq(handler=None, trigger=IRQ_FALLING|IRQ_RISING)
|
||||
STATIC mp_obj_t machine_pin_irq(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
enum { ARG_handler, ARG_trigger, ARG_wake };
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{ MP_QSTR_handler, MP_ARG_OBJ, {.u_obj = mp_const_none} },
|
||||
{ MP_QSTR_trigger, MP_ARG_INT, {.u_int = PIN_IRQ_MODE_RISING} },
|
||||
};
|
||||
machine_pin_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
|
||||
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
|
||||
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
|
||||
|
||||
if (n_args > 1 || kw_args->used != 0) {
|
||||
// configure irq
|
||||
self->pin_isr_cb = args[ARG_handler].u_obj;
|
||||
uint32_t trigger = args[ARG_trigger].u_int;
|
||||
|
||||
rt_pin_mode(self->pin, PIN_MODE_INPUT_PULLUP);
|
||||
rt_pin_attach_irq(self->pin, trigger, machine_pin_isr_handler, (void*)self);
|
||||
rt_pin_irq_enable(self->pin, PIN_IRQ_ENABLE);
|
||||
}
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_pin_irq_obj, 1, machine_pin_irq);
|
||||
|
||||
STATIC const mp_rom_map_elem_t machine_pin_locals_dict_table[] = {
|
||||
// instance methods
|
||||
{ MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_pin_init_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_value), MP_ROM_PTR(&machine_pin_value_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_name), MP_ROM_PTR(&machine_pin_name_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_pin), MP_ROM_PTR(&machine_pin_pin_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_irq), MP_ROM_PTR(&machine_pin_irq_obj) },
|
||||
|
||||
// class constants
|
||||
{ MP_ROM_QSTR(MP_QSTR_ALT_OD), MP_ROM_INT(GPIO_MODE_AF_OD) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_ALT_PP), MP_ROM_INT(GPIO_MODE_AF_PP) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_ANALOG), MP_ROM_INT(GPIO_MODE_ANALOG) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_IN), MP_ROM_INT(GPIO_MODE_IN) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_OUT_PP), MP_ROM_INT(GPIO_MODE_OUT_PP) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_OUT_OD), MP_ROM_INT(GPIO_MODE_OUT_OD) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_PULL_DOWN), MP_ROM_INT(GPIO_PULLDOWN) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_PULL_NONE), MP_ROM_INT(GPIO_NOPULL) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_PULL_UP), MP_ROM_INT(GPIO_PULLUP) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_IRQ_RISING), MP_ROM_INT(PIN_IRQ_MODE_RISING) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_IRQ_FALLING), MP_ROM_INT(PIN_IRQ_MODE_FALLING) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_IRQ_RISING_FALLING), MP_ROM_INT(PIN_IRQ_MODE_RISING_FALLING) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_IRQ_LOW_LEVEL), MP_ROM_INT(PIN_IRQ_MODE_LOW_LEVEL) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_IRQ_HIGH_LEVEL), MP_ROM_INT(PIN_IRQ_MODE_HIGH_LEVEL) },
|
||||
};
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(machine_pin_locals_dict, machine_pin_locals_dict_table);
|
||||
|
||||
STATIC const mp_pin_p_t machine_pin_pin_p = {
|
||||
.ioctl = machine_pin_ioctl,
|
||||
};
|
||||
|
||||
const mp_obj_type_t machine_pin_type = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_Pin,
|
||||
.print = machine_pin_print,
|
||||
.make_new = mp_pin_make_new,
|
||||
.call = machine_pin_call,
|
||||
.protocol = &machine_pin_pin_p,
|
||||
.locals_dict = (mp_obj_t)&machine_pin_locals_dict,
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,276 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2019 ChenYong (chenyong@rt-thread.com)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "py/nlr.h"
|
||||
#include "py/runtime.h"
|
||||
#include "modmachine.h"
|
||||
#include "mphalport.h"
|
||||
|
||||
#ifdef MICROPYTHON_USING_MACHINE_PWM
|
||||
|
||||
#include <rtthread.h>
|
||||
#include <drivers/rt_drv_pwm.h>
|
||||
|
||||
#define MP_PWM_PULSE_MAX 255
|
||||
#define MP_PWM_PERIOD_GET(freq) (1000000000 / (freq))
|
||||
#define MP_PWM_PULSE_GET(period, duty) ((period) / MP_PWM_PULSE_MAX * (duty))
|
||||
|
||||
extern const mp_obj_type_t machine_pwm_type;
|
||||
|
||||
typedef struct _machine_pwm_obj_t {
|
||||
mp_obj_base_t base;
|
||||
struct rt_device_pwm *pwm_device;
|
||||
char dev_name[RT_NAME_MAX];
|
||||
uint8_t is_init;
|
||||
int8_t id;
|
||||
uint8_t channel;
|
||||
uint8_t duty;
|
||||
uint32_t freq;
|
||||
} machine_pwm_obj_t;
|
||||
|
||||
STATIC void machine_pwm_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
|
||||
machine_pwm_obj_t *self = self_in;
|
||||
|
||||
mp_printf(print, "PWM(%p; ", self);
|
||||
if (self->id >= 0) {
|
||||
mp_printf(print, "pwm_id=%d, ", self->id);
|
||||
} else {
|
||||
mp_printf(print, "pwm_name=%s, ", self->dev_name);
|
||||
}
|
||||
mp_printf(print, "channel=%d, ", self->channel);
|
||||
mp_printf(print, "freq=%d, ", self->freq);
|
||||
mp_printf(print, "duty=%d)", self->duty);
|
||||
}
|
||||
|
||||
STATIC void error_check(bool status, const char *msg) {
|
||||
if (!status) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, msg));
|
||||
}
|
||||
}
|
||||
|
||||
STATIC void machine_pwm_init_helper(machine_pwm_obj_t *self,
|
||||
size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
rt_err_t result = RT_EOK;
|
||||
uint32_t period = 0, pulse = 0;
|
||||
char pwm_dev_name[RT_NAME_MAX];
|
||||
struct rt_device_pwm *pwm_device = RT_NULL;
|
||||
enum { ARG_channel, ARG_freq, ARG_duty };
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{ MP_QSTR_channel, MP_ARG_INT, {.u_int = 0} },
|
||||
{ MP_QSTR_freq, MP_ARG_INT, {.u_int = 1} },
|
||||
{ MP_QSTR_duty, MP_ARG_INT, {.u_int = 0} },
|
||||
};
|
||||
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
|
||||
mp_arg_parse_all(n_args, pos_args, kw_args,
|
||||
MP_ARRAY_SIZE(allowed_args), allowed_args, args);
|
||||
|
||||
int tval = args[ARG_channel].u_int;
|
||||
if ((tval < 0) || (tval > 4)) {
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError,
|
||||
"Bad channel %d", tval));
|
||||
}
|
||||
self->channel = tval;
|
||||
|
||||
tval = args[ARG_freq].u_int;
|
||||
if ((tval < 1) || (tval > 156250)) {
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError,
|
||||
"Bad frequency %d", tval));
|
||||
}
|
||||
self->freq = tval;
|
||||
|
||||
tval = args[ARG_duty].u_int;
|
||||
if ((tval < 0) || (tval > 255)) {
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError,
|
||||
"Bad duty %d", tval));
|
||||
}
|
||||
self->duty = tval;
|
||||
|
||||
if (self->id >= 0) {
|
||||
rt_snprintf(pwm_dev_name, sizeof(pwm_dev_name), "pwm%d", self->id);
|
||||
} else {
|
||||
rt_strncpy(pwm_dev_name, self->dev_name, RT_NAME_MAX);
|
||||
}
|
||||
|
||||
pwm_device = (struct rt_device_pwm *) rt_device_find(pwm_dev_name);
|
||||
if (pwm_device == RT_NULL || pwm_device->parent.type != RT_Device_Class_Miscellaneous) {
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError,
|
||||
"PWM(%s) don't exist", pwm_dev_name));
|
||||
}
|
||||
self->pwm_device = pwm_device;
|
||||
|
||||
// get period number by frequency
|
||||
period = MP_PWM_PERIOD_GET(self->freq);
|
||||
// get pulse number by duty
|
||||
pulse = MP_PWM_PULSE_GET(period, self->duty);
|
||||
|
||||
result = rt_pwm_set(pwm_device, self->channel, period, pulse);
|
||||
error_check(result == RT_EOK, "PWM set information error");
|
||||
|
||||
result = rt_pwm_enable(pwm_device, self->channel);
|
||||
error_check(result == RT_EOK, "PWM enable error");
|
||||
|
||||
self->is_init = RT_TRUE;
|
||||
}
|
||||
|
||||
STATIC mp_obj_t machine_pwm_make_new(const mp_obj_type_t *type,
|
||||
size_t n_args, size_t n_kw, const mp_obj_t *args) {
|
||||
mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true);
|
||||
|
||||
// create PWM object from the given pin
|
||||
machine_pwm_obj_t *self = m_new_obj(machine_pwm_obj_t);
|
||||
self->base.type = &machine_pwm_type;
|
||||
self->is_init = RT_FALSE;
|
||||
|
||||
// check input PWM device name or ID
|
||||
if (mp_obj_is_small_int(args[0])) {
|
||||
self->id = mp_obj_get_int(args[0]);
|
||||
} else if (mp_obj_is_qstr(args[0])) {
|
||||
self->id = -1;
|
||||
rt_strncpy(self->dev_name, mp_obj_str_get_str(args[0]), RT_NAME_MAX);
|
||||
} else {
|
||||
error_check(0, "Input PWM device name or ID error.");
|
||||
}
|
||||
|
||||
self->channel = 0;
|
||||
self->freq = 1;
|
||||
self->duty = 0;
|
||||
|
||||
mp_map_t kw_args;
|
||||
mp_map_init_fixed_table(&kw_args, n_kw, args + n_args);
|
||||
machine_pwm_init_helper(self, n_args - 1, args + 1, &kw_args);
|
||||
|
||||
return MP_OBJ_FROM_PTR(self);
|
||||
}
|
||||
|
||||
STATIC mp_obj_t machine_pwm_init(size_t n_args,
|
||||
const mp_obj_t *args, mp_map_t *kw_args) {
|
||||
machine_pwm_init_helper(args[0], n_args - 1, args + 1, kw_args);
|
||||
return mp_const_none;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_KW(machine_pwm_init_obj, 1, machine_pwm_init);
|
||||
|
||||
STATIC mp_obj_t machine_pwm_deinit(mp_obj_t self_in) {
|
||||
machine_pwm_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
rt_err_t result = RT_EOK;
|
||||
|
||||
if (self->is_init == RT_TRUE) {
|
||||
result = rt_pwm_disable(self->pwm_device, self->channel);
|
||||
error_check(result == RT_EOK, "PWM disable error");
|
||||
self->is_init = RT_FALSE;
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_pwm_deinit_obj, machine_pwm_deinit);
|
||||
|
||||
STATIC mp_obj_t machine_pwm_freq(size_t n_args, const mp_obj_t *args) {
|
||||
machine_pwm_obj_t *self = MP_OBJ_TO_PTR(args[0]);
|
||||
uint32_t period = 0, pulse = 0;
|
||||
rt_err_t result = RT_EOK;
|
||||
|
||||
error_check(self->is_init == RT_TRUE, "PWM device uninitialized");
|
||||
|
||||
if (n_args == 1) {
|
||||
// get
|
||||
return MP_OBJ_NEW_SMALL_INT(self->freq);
|
||||
}
|
||||
|
||||
// set
|
||||
int tval = mp_obj_get_int(args[1]);
|
||||
if ((tval < 1) || (tval > 156250)) {
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError,
|
||||
"Bad frequency %d", tval));
|
||||
}
|
||||
|
||||
// get period number by frequency
|
||||
period = MP_PWM_PERIOD_GET(tval);
|
||||
// get pulse number by duty
|
||||
pulse = MP_PWM_PULSE_GET(period, self->duty);
|
||||
|
||||
result = rt_pwm_set(self->pwm_device, self->channel, period, pulse);
|
||||
error_check(result == RT_EOK, "PWM set information error");
|
||||
self->freq = tval;
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_pwm_freq_obj, 1, 2, machine_pwm_freq);
|
||||
|
||||
STATIC mp_obj_t machine_pwm_duty(size_t n_args, const mp_obj_t *args) {
|
||||
machine_pwm_obj_t *self = MP_OBJ_TO_PTR(args[0]);
|
||||
uint32_t period = 0, pulse = 0;
|
||||
rt_err_t result = RT_EOK;
|
||||
|
||||
error_check(self->is_init == RT_TRUE, "PWM device uninitialized");
|
||||
|
||||
if (n_args == 1) {
|
||||
// get
|
||||
return MP_OBJ_NEW_SMALL_INT(self->duty);
|
||||
}
|
||||
|
||||
// set
|
||||
int tval = mp_obj_get_int(args[1]);
|
||||
if ((tval < 0) || (tval > 255)) {
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError,
|
||||
"Bad duty %d", tval));
|
||||
}
|
||||
|
||||
// get period number by frequency
|
||||
period = MP_PWM_PERIOD_GET(self->freq);
|
||||
// get pulse number by duty
|
||||
pulse = MP_PWM_PULSE_GET(period, tval);
|
||||
|
||||
result = rt_pwm_set(self->pwm_device, self->channel, period, pulse);
|
||||
error_check(result == RT_EOK, "PWM set information error");
|
||||
self->duty = tval;
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_pwm_duty_obj,
|
||||
1, 2, machine_pwm_duty);
|
||||
|
||||
STATIC const mp_rom_map_elem_t machine_pwm_locals_dict_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_pwm_init_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_pwm_deinit_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_freq), MP_ROM_PTR(&machine_pwm_freq_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_duty), MP_ROM_PTR(&machine_pwm_duty_obj) },
|
||||
};
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(machine_pwm_locals_dict,
|
||||
machine_pwm_locals_dict_table);
|
||||
|
||||
const mp_obj_type_t machine_pwm_type = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_PWM,
|
||||
.print = machine_pwm_print,
|
||||
.make_new = machine_pwm_make_new,
|
||||
.locals_dict = (mp_obj_dict_t *) &machine_pwm_locals_dict,
|
||||
};
|
||||
|
||||
#endif // MICROPYTHON_USING_MACHINE_PWM
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2019 ChenYong (chenyong@rt-thread.com)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef MICROPY_INCLUDED_MACHINE_PWM_H
|
||||
#define MICROPY_INCLUDED_MACHINE_PWM_H
|
||||
|
||||
#include "py/obj.h"
|
||||
#include <rtthread.h>
|
||||
|
||||
extern const mp_obj_type_t machine_pwm_type;
|
||||
|
||||
#endif // MICROPY_INCLUDED_MACHINE_PWM_H
|
||||
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2019 ChenYong (chenyong@rt-thread.com)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "py/nlr.h"
|
||||
#include "py/obj.h"
|
||||
#include "py/runtime.h"
|
||||
#include "py/mphal.h"
|
||||
#include "lib/timeutils/timeutils.h"
|
||||
#include "modmachine.h"
|
||||
|
||||
#ifdef MICROPYTHON_USING_MACHINE_RTC
|
||||
|
||||
#include <rtthread.h>
|
||||
#include <drivers/rtc.h>
|
||||
#include <time.h>
|
||||
|
||||
#define MP_YEAR_BASE 1900
|
||||
|
||||
const mp_obj_type_t machine_rtc_type;
|
||||
|
||||
// singleton RTC object
|
||||
STATIC const mp_obj_base_t machine_rtc_obj = {&machine_rtc_type};
|
||||
|
||||
STATIC void error_check(bool status, const char *msg) {
|
||||
if (!status) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, msg));
|
||||
}
|
||||
}
|
||||
|
||||
STATIC mp_obj_t machine_rtc_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
|
||||
#define MP_RTC_DEV_NAME "rtc"
|
||||
rt_device_t rtc_deivce = RT_NULL;
|
||||
|
||||
// check arguments
|
||||
mp_arg_check_num(n_args, n_kw, 0, 0, false);
|
||||
|
||||
// check RTC device
|
||||
rtc_deivce = rt_device_find(MP_RTC_DEV_NAME);
|
||||
if (rtc_deivce == RT_NULL || rtc_deivce->type != RT_Device_Class_RTC) {
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "RTC(%s) don't exist", MP_RTC_DEV_NAME));
|
||||
}
|
||||
|
||||
// return constant object
|
||||
return (mp_obj_t)&machine_rtc_obj;
|
||||
}
|
||||
|
||||
STATIC mp_obj_t machine_rtc_datetime_helper(mp_uint_t n_args, const mp_obj_t *args) {
|
||||
if (n_args == 1) {
|
||||
struct tm *tblock;
|
||||
time_t t;
|
||||
// Get time
|
||||
t = time(RT_NULL);
|
||||
tblock = localtime(&t);
|
||||
|
||||
mp_uint_t seconds = timeutils_mktime(tblock->tm_year + MP_YEAR_BASE, tblock->tm_mon + 1, tblock->tm_mday,
|
||||
tblock->tm_hour, tblock->tm_min, tblock->tm_sec);
|
||||
timeutils_struct_time_t tm;
|
||||
timeutils_seconds_since_2000_to_struct_time(seconds, &tm);
|
||||
|
||||
mp_obj_t tuple[8] = {
|
||||
mp_obj_new_int(tm.tm_year),
|
||||
mp_obj_new_int(tm.tm_mon),
|
||||
mp_obj_new_int(tm.tm_mday),
|
||||
mp_obj_new_int(tm.tm_wday),
|
||||
mp_obj_new_int(tm.tm_hour),
|
||||
mp_obj_new_int(tm.tm_min),
|
||||
mp_obj_new_int(tm.tm_sec),
|
||||
mp_obj_new_int(0)
|
||||
};
|
||||
|
||||
return mp_obj_new_tuple(8, tuple);
|
||||
} else {
|
||||
// Set time
|
||||
rt_err_t result;
|
||||
mp_obj_t *items;
|
||||
|
||||
mp_obj_get_array_fixed_n(args[1], 8, &items);
|
||||
result = set_date(mp_obj_get_int(items[0]), mp_obj_get_int(items[1]), mp_obj_get_int(items[2]));
|
||||
error_check(result == RT_EOK, "Set date error");
|
||||
result = set_time(mp_obj_get_int(items[4]), mp_obj_get_int(items[5]), mp_obj_get_int(items[6]));
|
||||
error_check(result == RT_EOK, "Set time error");
|
||||
return mp_const_none;
|
||||
}
|
||||
}
|
||||
|
||||
STATIC mp_obj_t machine_rtc_now(mp_uint_t n_args, const mp_obj_t *args) {
|
||||
return machine_rtc_datetime_helper(1, args);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_rtc_now_obj, 0, 1, machine_rtc_now);
|
||||
|
||||
STATIC mp_obj_t machine_rtc_init(mp_uint_t n_args, const mp_obj_t *args) {
|
||||
return machine_rtc_datetime_helper(n_args, args);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_rtc_init_obj, 1, 2, machine_rtc_init);
|
||||
|
||||
STATIC mp_obj_t machine_rtc_deinit(mp_uint_t n_args, const mp_obj_t *args) {
|
||||
rt_err_t result;
|
||||
struct tm tblock;
|
||||
|
||||
tblock.tm_year = 2015 - MP_YEAR_BASE;
|
||||
tblock.tm_mon = 0;
|
||||
tblock.tm_mday = 1;
|
||||
tblock.tm_hour = 0;
|
||||
tblock.tm_min = 0;
|
||||
tblock.tm_sec = 0;
|
||||
result = set_date(tblock.tm_year + MP_YEAR_BASE, tblock.tm_mon + 1, tblock.tm_mday);
|
||||
error_check(result == RT_EOK, "Set date error");
|
||||
result = set_time(tblock.tm_hour, tblock.tm_min, tblock.tm_sec);
|
||||
error_check(result == RT_EOK, "Set time error");
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_rtc_deinit_obj, 0, 1, machine_rtc_deinit);
|
||||
|
||||
STATIC const mp_rom_map_elem_t machine_rtc_locals_dict_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_rtc_init_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_rtc_deinit_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_now), MP_ROM_PTR(&machine_rtc_now_obj) },
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(machine_rtc_locals_dict, machine_rtc_locals_dict_table);
|
||||
|
||||
const mp_obj_type_t machine_rtc_type = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_RTC,
|
||||
.make_new = machine_rtc_make_new,
|
||||
.locals_dict = (mp_obj_t) &machine_rtc_locals_dict,
|
||||
};
|
||||
|
||||
#endif // MICROPYTHON_USING_MACHINE_RTC
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2019 ChenYong (chenyong@rt-thread.com)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef MICROPY_INCLUDED_MACHINE_RTC_H
|
||||
#define MICROPY_INCLUDED_MACHINE_RTC_H
|
||||
|
||||
#include "py/obj.h"
|
||||
#include <rtthread.h>
|
||||
|
||||
extern const mp_obj_type_t machine_rtc_type;
|
||||
|
||||
#endif // MICROPY_INCLUDED_MACHINE_RTC_H
|
||||
@@ -0,0 +1,270 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2019 ChenYong (chenyong@rt-thread.com)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "py/obj.h"
|
||||
#include "py/runtime.h"
|
||||
#include "modmachine.h"
|
||||
#include "mphalport.h"
|
||||
|
||||
#ifdef MICROPYTHON_USING_MACHINE_TIMER
|
||||
|
||||
#include <rtthread.h>
|
||||
#include <drivers/hwtimer.h>
|
||||
#include "machine_timer.h"
|
||||
|
||||
#define MAX_TIMER 17
|
||||
|
||||
typedef struct _machine_timer_obj_t {
|
||||
mp_obj_base_t base;
|
||||
rt_device_t timer_device;
|
||||
char dev_name[RT_NAME_MAX];
|
||||
mp_obj_t timeout_cb;
|
||||
int8_t timerid;
|
||||
uint32_t timeout;
|
||||
rt_bool_t is_repeat;
|
||||
rt_bool_t is_init;
|
||||
} machine_timer_obj_t;
|
||||
|
||||
const mp_obj_type_t machine_timer_type;
|
||||
|
||||
STATIC void error_check(bool status, const char *msg) {
|
||||
if (!status) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, msg));
|
||||
}
|
||||
}
|
||||
|
||||
STATIC void machine_timer_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
|
||||
machine_timer_obj_t *self = self_in;
|
||||
|
||||
mp_printf(print, "Timer(%p; ", self);
|
||||
|
||||
if (self->timerid >= 0) {
|
||||
mp_printf(print, "timer_id=%d, ", self->timerid);
|
||||
} else {
|
||||
mp_printf(print, "timer_name=%s, ", self->dev_name);
|
||||
}
|
||||
mp_printf(print, "period=%d, ", self->timeout);
|
||||
mp_printf(print, "auto_reload=%d)", self->is_repeat);
|
||||
}
|
||||
|
||||
STATIC mp_obj_t machine_timer_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
|
||||
machine_timer_obj_t *self = m_new_obj(machine_timer_obj_t);
|
||||
char timer_dev_name[RT_NAME_MAX] = {0};
|
||||
|
||||
// check arguments
|
||||
mp_arg_check_num(n_args, n_kw, 1, 1, true);
|
||||
|
||||
// check input timer device name or ID
|
||||
if (mp_obj_is_small_int(args[0])) {
|
||||
int device_id = mp_obj_get_int(args[0]);
|
||||
self->timerid = device_id;
|
||||
self->timer_device->device_id = device_id;
|
||||
rt_snprintf(timer_dev_name, sizeof(timer_dev_name), "timer%d", mp_obj_get_int(args[0]));
|
||||
} else if (mp_obj_is_qstr(args[0])) {
|
||||
static int device_id = 0;
|
||||
self->timerid = -1;
|
||||
self->timer_device->device_id = device_id++;
|
||||
rt_strncpy(self->dev_name, mp_obj_str_get_str(args[0]), RT_NAME_MAX);
|
||||
rt_strncpy(timer_dev_name, self->dev_name, RT_NAME_MAX);
|
||||
} else {
|
||||
error_check(0, "Input ADC device name or ID error.");
|
||||
}
|
||||
|
||||
// find timer device
|
||||
self->timer_device = rt_device_find(timer_dev_name);
|
||||
if (self->timer_device == RT_NULL || self->timer_device->type != RT_Device_Class_Timer) {
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "Timer(%s) don't exist", timer_dev_name));
|
||||
}
|
||||
|
||||
// initialize timer device
|
||||
self->base.type = &machine_timer_type;
|
||||
self->timeout = 0;
|
||||
self->timeout_cb = RT_NULL;
|
||||
self->is_repeat = RT_TRUE;
|
||||
self->is_init = RT_FALSE;
|
||||
|
||||
// return constant object
|
||||
return MP_OBJ_FROM_PTR(self);
|
||||
}
|
||||
|
||||
static machine_timer_obj_t *timer_self[MAX_TIMER] = {RT_NULL};
|
||||
|
||||
STATIC mp_obj_t machine_timer_deinit(mp_obj_t self_in) {
|
||||
machine_timer_obj_t *self = self_in;
|
||||
rt_err_t result = RT_EOK;
|
||||
|
||||
if (self->is_init == RT_TRUE) {
|
||||
result = rt_device_close(self->timer_device);
|
||||
error_check(result == RT_EOK, "Timer device close error");
|
||||
self->is_init = RT_FALSE;
|
||||
timer_self[self->timer_device->device_id] = RT_NULL;
|
||||
}
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_timer_deinit_obj, machine_timer_deinit);
|
||||
|
||||
STATIC rt_err_t timer_event_handler(rt_device_t dev, rt_size_t size) {
|
||||
machine_timer_obj_t *self = timer_self[dev->device_id];
|
||||
|
||||
mp_sched_schedule(self->timeout_cb, MP_OBJ_FROM_PTR(self));
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
STATIC mp_obj_t machine_timer_init(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
|
||||
machine_timer_obj_t *self = (machine_timer_obj_t *)args[0];
|
||||
rt_bool_t result = RT_EOK;
|
||||
int mode = 0;
|
||||
|
||||
enum {
|
||||
ARG_mode,
|
||||
ARG_period,
|
||||
ARG_callback,
|
||||
};
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{ MP_QSTR_mode, MP_ARG_INT, {.u_int = 1} },
|
||||
{ MP_QSTR_period, MP_ARG_INT, {.u_int = 0xffffffff} },
|
||||
{ MP_QSTR_callback, MP_ARG_OBJ, {.u_obj = mp_const_none} },
|
||||
};
|
||||
|
||||
mp_arg_val_t dargs[MP_ARRAY_SIZE(allowed_args)];
|
||||
mp_arg_parse_all(n_args - 1, args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, dargs);
|
||||
|
||||
if (2 == n_args) {
|
||||
self->timeout = dargs[0].u_int;
|
||||
} else if (3 == n_args) {
|
||||
self->is_repeat = dargs[ARG_mode].u_int;
|
||||
self->timeout = dargs[ARG_period].u_int;
|
||||
} else if (4 == n_args) {
|
||||
self->is_repeat = dargs[ARG_mode].u_int;
|
||||
self->timeout = dargs[ARG_period].u_int;
|
||||
self->timeout_cb = dargs[ARG_callback].u_obj;
|
||||
} else {
|
||||
mp_raise_ValueError("invalid format");
|
||||
}
|
||||
|
||||
error_check(self->timeout > 0, "Set timeout value error");
|
||||
|
||||
if (self->is_init == RT_FALSE)
|
||||
{
|
||||
// open timer device
|
||||
result = rt_device_open(self->timer_device, RT_DEVICE_OFLAG_RDWR);
|
||||
error_check(result == RT_EOK, "Timer device open error");
|
||||
}
|
||||
|
||||
if (self->timeout_cb != RT_NULL) {
|
||||
// set callback timer
|
||||
if (timer_self[self->timer_device->device_id] && timer_self[self->timer_device->device_id] != self) {
|
||||
error_check(result == RT_EOK, "Timer device callback function already exists");
|
||||
} else {
|
||||
timer_self[self->timer_device->device_id] = self;
|
||||
}
|
||||
result = rt_device_set_rx_indicate(self->timer_device, timer_event_handler);
|
||||
error_check(result == RT_EOK, "Timer set timout callback error");
|
||||
}
|
||||
|
||||
// set timer mode
|
||||
mode = self->is_repeat ? HWTIMER_MODE_PERIOD : HWTIMER_MODE_ONESHOT;
|
||||
result = rt_device_control(self->timer_device, HWTIMER_CTRL_MODE_SET, &mode);
|
||||
error_check(result == RT_EOK, "Timer set mode error");
|
||||
|
||||
if (self->timeout) {
|
||||
rt_hwtimerval_t timeout_s;
|
||||
rt_size_t len;
|
||||
|
||||
timeout_s.sec = self->timeout / 1000; // second
|
||||
timeout_s.usec = self->timeout % 1000; // microsecond
|
||||
|
||||
len = rt_device_write(self->timer_device, 0, &timeout_s, sizeof(timeout_s));
|
||||
error_check(len == sizeof(timeout_s), "Timer set timout error");
|
||||
}
|
||||
|
||||
self->is_init = RT_TRUE;
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_timer_init_obj, 1, machine_timer_init);
|
||||
|
||||
|
||||
STATIC mp_obj_t machine_timer_callback(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
|
||||
machine_timer_obj_t *self = (machine_timer_obj_t *)args[0];
|
||||
rt_bool_t result = RT_EOK;
|
||||
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{ MP_QSTR_callback, MP_ARG_OBJ, {.u_obj = mp_const_none} },
|
||||
};
|
||||
|
||||
mp_arg_val_t dargs[MP_ARRAY_SIZE(allowed_args)];
|
||||
mp_arg_parse_all(n_args - 1, args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, dargs);
|
||||
|
||||
self->timeout_cb = dargs[0].u_obj;
|
||||
|
||||
if(n_args == 1)
|
||||
{
|
||||
self->timeout_cb = RT_NULL;
|
||||
self->timer_device->rx_indicate = RT_NULL;//Log-off callback function
|
||||
}
|
||||
else if(n_args == 2)
|
||||
{
|
||||
if(self->timeout_cb != mp_const_none)
|
||||
{
|
||||
timer_self[self->timer_device->device_id] = self;
|
||||
result = rt_device_set_rx_indicate(self->timer_device, timer_event_handler); //set callback timer
|
||||
error_check(result == RT_EOK, "Timer set timout callback error");
|
||||
}
|
||||
else
|
||||
{
|
||||
self->timeout_cb = RT_NULL;
|
||||
self->timer_device->rx_indicate = RT_NULL;//Log-off callback function
|
||||
}
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_timer_callback_obj, 0,machine_timer_callback);
|
||||
|
||||
STATIC const mp_rom_map_elem_t machine_timer_locals_dict_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_timer_deinit_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_timer_init_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_callback), MP_ROM_PTR(&machine_timer_callback_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_ONE_SHOT), MP_ROM_INT(RT_FALSE) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_PERIODIC), MP_ROM_INT(RT_TRUE) },
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(machine_timer_locals_dict, machine_timer_locals_dict_table);
|
||||
|
||||
const mp_obj_type_t machine_timer_type = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_Timer,
|
||||
.print = machine_timer_print,
|
||||
.make_new = machine_timer_make_new,
|
||||
.locals_dict = (mp_obj_t) &machine_timer_locals_dict,
|
||||
};
|
||||
|
||||
#endif // MICROPYTHON_USING_MACHINE_TIMER
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2019 ChenYong (chenyong@rt-thread.com)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef MICROPY_INCLUDED_MACHINE_TIMER_H
|
||||
#define MICROPY_INCLUDED_MACHINE_TIMER_H
|
||||
|
||||
#include "py/obj.h"
|
||||
#include <rtthread.h>
|
||||
|
||||
extern const mp_obj_type_t machine_timer_type;
|
||||
|
||||
#endif // MICROPY_INCLUDED_MACHINE_TIMER_H
|
||||
|
||||
@@ -0,0 +1,274 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018 SummerGift <zhangyuan@rt-thread.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "py/runtime.h"
|
||||
#include "py/mphal.h"
|
||||
#include "py/mperrno.h"
|
||||
#include "py/stream.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
#include "machine_uart.h"
|
||||
#include "rtdevice.h"
|
||||
|
||||
#ifdef MICROPYTHON_USING_MACHINE_UART
|
||||
|
||||
#ifndef RT_USING_SERIAL
|
||||
#error "Please define the RT_USING_SERIAL on 'rtconfig.h'"
|
||||
#endif
|
||||
|
||||
typedef struct _machine_uart_obj_t {
|
||||
mp_obj_base_t base;
|
||||
struct rt_serial_device *uart_device;
|
||||
}machine_uart_obj_t;
|
||||
|
||||
STATIC void machine_uart_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
|
||||
machine_uart_obj_t *self = (machine_uart_obj_t*) self_in;
|
||||
mp_printf(print, "uart( device port : %s,baud_rate = %d, data_bits = %d, parity = %d, stop_bits = %d )",
|
||||
self->uart_device->parent.parent.name,
|
||||
self->uart_device->config.baud_rate,
|
||||
self->uart_device->config.data_bits,
|
||||
self->uart_device->config.parity,
|
||||
self->uart_device->config.stop_bits);
|
||||
}
|
||||
|
||||
STATIC mp_obj_t machine_uart_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
|
||||
mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true);
|
||||
char uart_dev_name[RT_NAME_MAX];
|
||||
snprintf(uart_dev_name, sizeof(uart_dev_name), "uart%d", mp_obj_get_int(args[0]));
|
||||
|
||||
struct rt_serial_device *rt_serial_device = (struct rt_serial_device *) rt_device_find(uart_dev_name);
|
||||
if (rt_serial_device == RT_NULL || rt_serial_device->parent.type != RT_Device_Class_Char) {
|
||||
mp_printf(&mp_plat_print, "ERROR: UART device %s not found!\n", uart_dev_name);
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "UART(%s) doesn't exist", uart_dev_name));
|
||||
}
|
||||
|
||||
rt_err_t result;
|
||||
result = rt_device_open((rt_device_t)rt_serial_device, RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_INT_RX );
|
||||
if (result != RT_EOK)
|
||||
{
|
||||
mp_printf(&mp_plat_print, "ERROR: UART device %s can't open!\n", uart_dev_name);
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "UART(%s) can't open", uart_dev_name));
|
||||
}
|
||||
|
||||
// create new uart object
|
||||
machine_uart_obj_t *self = m_new_obj(machine_uart_obj_t);
|
||||
self->base.type = &machine_uart_type;
|
||||
self->uart_device = rt_serial_device;
|
||||
return (mp_obj_t) self;
|
||||
}
|
||||
|
||||
/// \method init(baudrate, bits=8, parity=None, stop=1, *, timeout=1000, timeout_char=0, flow=0, read_buf_len=64)
|
||||
///
|
||||
/// Initialise the UART bus with the given parameters:
|
||||
///
|
||||
/// - `baudrate` is the clock rate.
|
||||
/// - `bits` is the number of bits per byte, 7, 8 or 9.
|
||||
/// - `parity` is the parity, `None`, 0 (even) or 1 (odd).
|
||||
/// - `stop` is the number of stop bits, 1 or 2.
|
||||
/// - `timeout` is the timeout in milliseconds to wait for the first character.
|
||||
/// - `timeout_char` is the timeout in milliseconds to wait between characters.
|
||||
/// - `flow` is RTS | CTS where RTS == 256, CTS == 512
|
||||
/// - `read_buf_len` is the character length of the read buffer (0 to disable).
|
||||
///
|
||||
STATIC mp_obj_t machine_uart_init_helper(machine_uart_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{ MP_QSTR_baudrate, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 9600} },
|
||||
{ MP_QSTR_bits, MP_ARG_INT, {.u_int = 8} },
|
||||
{ MP_QSTR_parity, MP_ARG_OBJ, {.u_obj = mp_const_none} },
|
||||
{ MP_QSTR_stop, MP_ARG_INT, {.u_int = 1} },
|
||||
{ MP_QSTR_flow, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, // rt-thread does not support
|
||||
{ MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1000} },
|
||||
{ MP_QSTR_timeout_char, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
|
||||
{ MP_QSTR_read_buf_len, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 64} },
|
||||
};
|
||||
|
||||
// parse args
|
||||
struct {
|
||||
mp_arg_val_t baudrate, bits, parity, stop, flow, timeout, timeout_char, read_buf_len;
|
||||
} args;
|
||||
mp_arg_parse_all(n_args, pos_args, kw_args,
|
||||
MP_ARRAY_SIZE(allowed_args), allowed_args, (mp_arg_val_t*)&args);
|
||||
|
||||
// set the UART configuration values
|
||||
struct rt_serial_device *uart_p = self->uart_device;
|
||||
struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
|
||||
|
||||
// baudrate
|
||||
config.baud_rate = args.baudrate.u_int;
|
||||
|
||||
// parity
|
||||
mp_int_t bits = args.bits.u_int;
|
||||
if (args.parity.u_obj == mp_const_none) {
|
||||
config.parity = PARITY_NONE;
|
||||
} else {
|
||||
mp_int_t parity = mp_obj_get_int(args.parity.u_obj);
|
||||
config.parity = (parity & 1) ? PARITY_ODD : PARITY_EVEN;
|
||||
//bits += 1; // STs convention has bits including parity, not all mcu
|
||||
}
|
||||
|
||||
// number of bits
|
||||
if (bits == 8) {
|
||||
config.data_bits = DATA_BITS_8;
|
||||
} else if (bits == 9) {
|
||||
config.data_bits = DATA_BITS_9;
|
||||
} else if (bits == 7) {
|
||||
config.data_bits = DATA_BITS_7;
|
||||
} else {
|
||||
mp_raise_ValueError("unsupported combination of bits and parity");
|
||||
}
|
||||
|
||||
// stop bits
|
||||
switch (args.stop.u_int) {
|
||||
case 1: config.stop_bits = STOP_BITS_1; break;
|
||||
default: config.stop_bits = STOP_BITS_2; break;
|
||||
}
|
||||
|
||||
//buffer size
|
||||
#if defined(RT_USING_SERIAL_V1)
|
||||
config.bufsz = args.read_buf_len.u_int;
|
||||
|
||||
#elif defined(RT_USING_SERIAL_V2)
|
||||
config.rx_bufsz = args.read_buf_len.u_int;
|
||||
config.tx_bufsz = args.read_buf_len.u_int;
|
||||
#endif
|
||||
rt_device_control((struct rt_device *) uart_p, RT_DEVICE_CTRL_CONFIG, &config);
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
|
||||
STATIC mp_obj_t machine_uart_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
|
||||
return machine_uart_init_helper(args[0], n_args - 1, args + 1, kw_args);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_uart_init_obj, 1, machine_uart_init);
|
||||
|
||||
STATIC mp_obj_t machine_uart_deinit(mp_obj_t self_in) {
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_uart_deinit_obj, machine_uart_deinit);
|
||||
|
||||
#define RETRY_TIMES 500
|
||||
|
||||
STATIC mp_obj_t machine_uart_writechar(mp_obj_t self_in, mp_obj_t char_in) {
|
||||
machine_uart_obj_t *self = self_in;
|
||||
uint16_t data = mp_obj_get_int(char_in);
|
||||
rt_size_t len = 0;
|
||||
rt_uint32_t timeout = 0;
|
||||
do
|
||||
{
|
||||
len = rt_device_write((struct rt_device *)(self->uart_device), 0, &data, 1);
|
||||
timeout++;
|
||||
}
|
||||
while (len != 1 && timeout < RETRY_TIMES);
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(machine_uart_writechar_obj, machine_uart_writechar);
|
||||
|
||||
#define UART_RX_EVENT (1 << 0)
|
||||
static struct rt_event event;
|
||||
|
||||
STATIC mp_obj_t machine_uart_readchar(mp_obj_t self_in) {
|
||||
machine_uart_obj_t *self = self_in;
|
||||
rt_uint32_t e;
|
||||
rt_uint8_t ch;
|
||||
|
||||
while (rt_device_read((struct rt_device *)(self->uart_device), 0, &ch, 1) != 1) {
|
||||
rt_event_recv(&event, UART_RX_EVENT, RT_EVENT_FLAG_AND |
|
||||
RT_EVENT_FLAG_CLEAR, RT_WAITING_FOREVER, &e);
|
||||
}
|
||||
|
||||
return MP_OBJ_NEW_SMALL_INT(ch);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_uart_readchar_obj, machine_uart_readchar);
|
||||
|
||||
STATIC const mp_rom_map_elem_t machine_uart_locals_dict_table[] = {
|
||||
// instance methods
|
||||
|
||||
{ MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_uart_init_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_uart_deinit_obj) },
|
||||
// { MP_ROM_QSTR(MP_QSTR_any), MP_ROM_PTR(&machine_uart_any_obj) },
|
||||
|
||||
/// \method read([nbytes])
|
||||
{ MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) },
|
||||
/// \method readline()
|
||||
{ MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj)},
|
||||
/// \method readinto(buf[, nbytes])
|
||||
{ MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) },
|
||||
/// \method write(buf)
|
||||
{ MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) },
|
||||
|
||||
{ MP_ROM_QSTR(MP_QSTR_writechar), MP_ROM_PTR(&machine_uart_writechar_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_readchar), MP_ROM_PTR(&machine_uart_readchar_obj) },
|
||||
// { MP_ROM_QSTR(MP_QSTR_sendbreak), MP_ROM_PTR(&pyb_uart_sendbreak_obj) },
|
||||
|
||||
// class constants
|
||||
// { MP_ROM_QSTR(MP_QSTR_RTS), MP_ROM_INT(UART_HWCONTROL_RTS) },
|
||||
// { MP_ROM_QSTR(MP_QSTR_CTS), MP_ROM_INT(UART_HWCONTROL_CTS) },
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(machine_uart_locals_dict, machine_uart_locals_dict_table);
|
||||
|
||||
STATIC mp_uint_t machine_uart_read(mp_obj_t self_in, void *buf_in, mp_uint_t size, int *errcode) {
|
||||
machine_uart_obj_t *self = self_in;
|
||||
byte *buf = buf_in;
|
||||
//TODO dfs sync read
|
||||
//MP_RTT_NOT_IMPL_PRINT;
|
||||
return rt_device_read((struct rt_device *)(self->uart_device), -1, buf, size);
|
||||
}
|
||||
|
||||
STATIC mp_uint_t machine_uart_write(mp_obj_t self_in, const void *buf_in, mp_uint_t size, int *errcode) {
|
||||
machine_uart_obj_t *self = self_in;
|
||||
const byte *buf = buf_in;
|
||||
//TODO dfs sync write
|
||||
//MP_RTT_NOT_IMPL_PRINT;
|
||||
return rt_device_write((struct rt_device *)(self->uart_device), -1, buf, size);
|
||||
}
|
||||
|
||||
STATIC mp_uint_t machine_uart_ioctl(mp_obj_t obj, mp_uint_t request, uintptr_t arg, int *errcode) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
STATIC const mp_stream_p_t uart_stream_p = {
|
||||
.read = machine_uart_read,
|
||||
.write = machine_uart_write,
|
||||
.ioctl = machine_uart_ioctl,
|
||||
.is_text = false,
|
||||
};
|
||||
|
||||
const mp_obj_type_t machine_uart_type = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_UART,
|
||||
.print = machine_uart_print,
|
||||
.make_new = machine_uart_make_new,
|
||||
.getiter = mp_identity_getiter,
|
||||
.iternext = mp_stream_unbuffered_iter,
|
||||
.protocol = &uart_stream_p,
|
||||
.locals_dict = (mp_obj_dict_t*)&machine_uart_locals_dict,
|
||||
};
|
||||
|
||||
#endif // MICROPYTHON_USING_MACHINE_UART
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 SummerGift <zhangyuan@rt-thread.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef MICROPY_INCLUDED_MACHINE_UART_H
|
||||
#define MICROPY_INCLUDED_MACHINE_UART_H
|
||||
|
||||
#include "py/obj.h"
|
||||
#include <rtthread.h>
|
||||
|
||||
extern const mp_obj_type_t machine_uart_type;
|
||||
|
||||
#endif // _MACHINE_UART_H
|
||||
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2019 ChenYong (chenyong@rt-thread.com)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "py/nlr.h"
|
||||
#include "py/obj.h"
|
||||
#include "py/runtime.h"
|
||||
#include "modmachine.h"
|
||||
#include "mphalport.h"
|
||||
|
||||
#ifdef MICROPYTHON_USING_MACHINE_WDT
|
||||
|
||||
#include <rtthread.h>
|
||||
#include <drivers/watchdog.h>
|
||||
#include "machine_wdt.h"
|
||||
|
||||
typedef struct _machine_wdt_obj_t {
|
||||
mp_obj_base_t base;
|
||||
rt_device_t wdt_device;
|
||||
}machine_wdt_obj_t;
|
||||
|
||||
const mp_obj_type_t machine_wdt_type;
|
||||
|
||||
STATIC void error_check(bool status, const char *msg) {
|
||||
if (!status) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, msg));
|
||||
}
|
||||
}
|
||||
|
||||
STATIC mp_obj_t machine_wdt_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {
|
||||
#define MP_WDT_DEV_NAME "wdt"
|
||||
machine_wdt_obj_t *self = m_new_obj(machine_wdt_obj_t);
|
||||
char wdt_dev_name[RT_NAME_MAX] = {0};
|
||||
rt_err_t result = RT_EOK;
|
||||
mp_int_t timeout = 5;
|
||||
|
||||
// check arguments
|
||||
mp_arg_check_num(n_args, n_kw, 0, 2, false);
|
||||
|
||||
if (n_args == 2) {
|
||||
// check input WDT device name or ID
|
||||
if (mp_obj_is_small_int(args[0])) {
|
||||
rt_snprintf(wdt_dev_name, sizeof(wdt_dev_name), "wdt%d", mp_obj_get_int(args[0]));
|
||||
} else if (mp_obj_is_qstr(args[0])) {
|
||||
rt_strncpy(wdt_dev_name, mp_obj_str_get_str(args[0]), RT_NAME_MAX);
|
||||
} else {
|
||||
error_check(0, "Input WDT device name or ID error.");
|
||||
}
|
||||
timeout = mp_obj_get_int(args[1]);
|
||||
error_check(timeout >= 1, "input timeout value error");
|
||||
} else if (n_args == 1) {
|
||||
if (mp_obj_is_small_int(args[0])) {
|
||||
timeout = mp_obj_get_int(args[0]);
|
||||
error_check(timeout >= 1, "input timeout value error");
|
||||
} else if (mp_obj_is_qstr(args[0])) {
|
||||
rt_strncpy(wdt_dev_name, mp_obj_str_get_str(args[0]), RT_NAME_MAX);
|
||||
} else {
|
||||
error_check(0, "Input WDT device name or ID error.");
|
||||
}
|
||||
} else {
|
||||
rt_strncpy(wdt_dev_name, MP_WDT_DEV_NAME, RT_NAME_MAX);
|
||||
}
|
||||
|
||||
self->base.type = &machine_wdt_type;
|
||||
// find WDT device
|
||||
self->wdt_device = rt_device_find(wdt_dev_name);
|
||||
if (self->wdt_device == RT_NULL || self->wdt_device->type != RT_Device_Class_Miscellaneous) {
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "WDT(%s) don't exist", wdt_dev_name));
|
||||
}
|
||||
|
||||
result = rt_device_init(self->wdt_device);
|
||||
error_check(result == RT_EOK, "WDT init error");
|
||||
|
||||
// set WDT device timout
|
||||
result = rt_device_control(self->wdt_device, RT_DEVICE_CTRL_WDT_SET_TIMEOUT, (void *)&timeout);
|
||||
error_check(result == RT_EOK, "WDT set timout error");
|
||||
|
||||
result = rt_device_control(self->wdt_device, RT_DEVICE_CTRL_WDT_START, RT_NULL);
|
||||
error_check(result == RT_EOK, "WDT start error");
|
||||
|
||||
// return constant object
|
||||
return MP_OBJ_FROM_PTR(self);
|
||||
}
|
||||
|
||||
STATIC mp_obj_t machine_wdt_feed(mp_obj_t self_in) {
|
||||
/* idle task feed */
|
||||
machine_wdt_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
rt_err_t result = RT_EOK;
|
||||
|
||||
result = rt_device_control(self->wdt_device, RT_DEVICE_CTRL_WDT_KEEPALIVE, RT_NULL);
|
||||
error_check(result == RT_EOK, "WDT feed failed");
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_wdt_feed_obj, machine_wdt_feed);
|
||||
|
||||
STATIC const mp_rom_map_elem_t machine_wdt_locals_dict_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR_feed), MP_ROM_PTR(&machine_wdt_feed_obj) },
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(machine_wdt_locals_dict, machine_wdt_locals_dict_table);
|
||||
|
||||
const mp_obj_type_t machine_wdt_type = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_WDT,
|
||||
.make_new = machine_wdt_make_new,
|
||||
.locals_dict = (mp_obj_t) &machine_wdt_locals_dict,
|
||||
};
|
||||
|
||||
#endif // MICROPYTHON_USING_MACHINE_WDT
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2019 ChenYong (chenyong@rt-thread.com)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef MICROPY_INCLUDED_MACHINE_WDT_H
|
||||
#define MICROPY_INCLUDED_MACHINE_WDT_H
|
||||
|
||||
#include "py/obj.h"
|
||||
#include <rtthread.h>
|
||||
|
||||
extern const mp_obj_type_t machine_wdt_type;
|
||||
|
||||
#endif // MICROPY_INCLUDED_MACHINE_WDT_H
|
||||
|
||||
@@ -0,0 +1,260 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Armink (armink.ztl@gmail.com)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "py/obj.h"
|
||||
#include "py/runtime.h"
|
||||
#include "py/gc.h"
|
||||
#include "lib/utils/pyexec.h"
|
||||
#include "extmod/machine_mem.h"
|
||||
#include "extmod/machine_signal.h"
|
||||
#include "extmod/machine_pulse.h"
|
||||
#include "extmod/machine_i2c.h"
|
||||
#include "extmod/machine_spi.h"
|
||||
#include "modmachine.h"
|
||||
#include "machine_uart.h"
|
||||
#include "machine_adc.h"
|
||||
#include "machine_pwm.h"
|
||||
#include "machine_lcd.h"
|
||||
#include "machine_rtc.h"
|
||||
#include "machine_wdt.h"
|
||||
#include "machine_timer.h"
|
||||
|
||||
#include <rthw.h>
|
||||
|
||||
#if MICROPY_PY_MACHINE
|
||||
|
||||
STATIC mp_obj_t machine_info(size_t n_args, const mp_obj_t *args) {
|
||||
#ifdef RT_USING_FINSH
|
||||
extern long list_thread(void);
|
||||
#endif
|
||||
// RT-Thread info
|
||||
{
|
||||
mp_printf(&mp_plat_print, "---------------------------------------------\n");
|
||||
mp_printf(&mp_plat_print, "RT-Thread\n");
|
||||
mp_printf(&mp_plat_print, "---------------------------------------------\n");
|
||||
|
||||
#ifdef RT_USING_FINSH
|
||||
extern void list_mem(void);
|
||||
extern void list_memheap(void);
|
||||
|
||||
#ifdef RT_USING_MEMHEAP_AS_HEAP
|
||||
list_memheap();
|
||||
#else
|
||||
list_mem();
|
||||
#endif
|
||||
|
||||
list_thread();
|
||||
#endif
|
||||
mp_printf(&mp_plat_print, "---------------------------------------------\n");
|
||||
}
|
||||
|
||||
// qstr info
|
||||
{
|
||||
mp_uint_t n_pool, n_qstr, n_str_data_bytes, n_total_bytes;
|
||||
qstr_pool_info(&n_pool, &n_qstr, &n_str_data_bytes, &n_total_bytes);
|
||||
mp_printf(&mp_plat_print, "qstr:\n n_pool=" UINT_FMT "\n n_qstr=" UINT_FMT "\n n_str_data_bytes=" UINT_FMT "\n n_total_bytes=" UINT_FMT "\n", n_pool, n_qstr, n_str_data_bytes, n_total_bytes);
|
||||
}
|
||||
mp_printf(&mp_plat_print, "---------------------------------------------\n");
|
||||
|
||||
// GC info
|
||||
{
|
||||
gc_info_t info;
|
||||
gc_info(&info);
|
||||
mp_printf(&mp_plat_print, "GC:\n");
|
||||
mp_printf(&mp_plat_print, " " UINT_FMT " total\n", info.total);
|
||||
mp_printf(&mp_plat_print, " " UINT_FMT " : " UINT_FMT "\n", info.used, info.free);
|
||||
mp_printf(&mp_plat_print, " 1=" UINT_FMT " 2=" UINT_FMT " m=" UINT_FMT "\n", info.num_1block, info.num_2block, info.max_block);
|
||||
}
|
||||
|
||||
// free space on flash
|
||||
{
|
||||
//TODO
|
||||
}
|
||||
|
||||
if (n_args == 1) {
|
||||
// arg given means dump gc allocation table
|
||||
gc_dump_alloc_table();
|
||||
}
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_info_obj, 0, 1, machine_info);
|
||||
|
||||
STATIC mp_obj_t machine_unique_id(void) {
|
||||
//TODO
|
||||
MP_RTT_NOT_IMPL_PRINT;
|
||||
return 0;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_0(machine_unique_id_obj, machine_unique_id);
|
||||
|
||||
STATIC mp_obj_t machine_reset(void) {
|
||||
//TODO
|
||||
MP_RTT_NOT_IMPL_PRINT;
|
||||
return mp_const_none;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_0(machine_reset_obj, machine_reset);
|
||||
|
||||
STATIC mp_obj_t machine_soft_reset(void) {
|
||||
pyexec_system_exit = PYEXEC_FORCED_EXIT;
|
||||
nlr_raise(mp_obj_new_exception(&mp_type_SystemExit));
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_0(machine_soft_reset_obj, machine_soft_reset);
|
||||
|
||||
/*
|
||||
* @param clkid - range 0~127 (e.g 0:SYSCLK 1:HCLK 2:PCLK1 etc)
|
||||
*
|
||||
* @return 0 - ok, -1 - no such clock
|
||||
*/
|
||||
RT_WEAK int mp_port_get_freq(int clkid, int *freq)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
STATIC mp_obj_t machine_freq(void) {
|
||||
int i;
|
||||
mp_obj_list_t *ret_list = m_new(mp_obj_list_t, 1);
|
||||
mp_obj_list_init(ret_list, 0);
|
||||
int freq;
|
||||
|
||||
for (i = 0; i < 128; i ++)
|
||||
{
|
||||
if (mp_port_get_freq(i, &freq) != 0)
|
||||
break;
|
||||
|
||||
mp_obj_list_append(ret_list, mp_obj_new_int(freq));
|
||||
}
|
||||
|
||||
return MP_OBJ_FROM_PTR(ret_list);
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_0(machine_freq_obj, machine_freq);
|
||||
|
||||
STATIC mp_obj_t pyb_wfi(void) {
|
||||
//TODO __WFI();
|
||||
MP_RTT_NOT_IMPL_PRINT;
|
||||
return mp_const_none;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_0(pyb_wfi_obj, pyb_wfi);
|
||||
|
||||
static rt_base_t int_lvl;
|
||||
STATIC mp_obj_t pyb_disable_irq(void) {
|
||||
int_lvl = rt_hw_interrupt_disable();
|
||||
return mp_obj_new_bool(1);
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_0(pyb_disable_irq_obj, pyb_disable_irq);
|
||||
|
||||
STATIC mp_obj_t pyb_enable_irq(size_t n_args, const mp_obj_t *arg) {
|
||||
if (n_args == 0) {
|
||||
rt_hw_interrupt_enable(int_lvl);
|
||||
} else {
|
||||
if (mp_obj_is_true(arg[0])) {
|
||||
rt_hw_interrupt_enable(int_lvl);
|
||||
} else {
|
||||
int_lvl = rt_hw_interrupt_disable();
|
||||
}
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_enable_irq_obj, 0, 1, pyb_enable_irq);
|
||||
|
||||
STATIC mp_obj_t machine_sleep (void) {
|
||||
//TODO
|
||||
MP_RTT_NOT_IMPL_PRINT;
|
||||
return mp_const_none;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_0(machine_sleep_obj, machine_sleep);
|
||||
|
||||
STATIC mp_obj_t machine_deepsleep (void) {
|
||||
//TODO
|
||||
MP_RTT_NOT_IMPL_PRINT;
|
||||
return mp_const_none;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_0(machine_deepsleep_obj, machine_deepsleep);
|
||||
|
||||
STATIC mp_obj_t machine_reset_cause(void) {
|
||||
//TODO
|
||||
MP_RTT_NOT_IMPL_PRINT;
|
||||
return MP_OBJ_NEW_SMALL_INT(42);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_reset_cause_obj, machine_reset_cause);
|
||||
|
||||
STATIC const mp_rom_map_elem_t machine_module_globals_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_umachine) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_info), MP_ROM_PTR(&machine_info_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_unique_id), MP_ROM_PTR(&machine_unique_id_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_reset), MP_ROM_PTR(&machine_reset_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_soft_reset), MP_ROM_PTR(&machine_soft_reset_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_freq), MP_ROM_PTR(&machine_freq_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_idle), MP_ROM_PTR(&pyb_wfi_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_sleep), MP_ROM_PTR(&machine_sleep_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_deepsleep), MP_ROM_PTR(&machine_deepsleep_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_reset_cause), MP_ROM_PTR(&machine_reset_cause_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_disable_irq), MP_ROM_PTR(&pyb_disable_irq_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_enable_irq), MP_ROM_PTR(&pyb_enable_irq_obj) },
|
||||
// { MP_ROM_QSTR(MP_QSTR_time_pulse_us), MP_ROM_PTR(&machine_time_pulse_us_obj) },
|
||||
#if MICROPY_PY_PIN
|
||||
{ MP_ROM_QSTR(MP_QSTR_Pin), MP_ROM_PTR(&machine_pin_type) },
|
||||
#endif
|
||||
{ MP_ROM_QSTR(MP_QSTR_Signal), MP_ROM_PTR(&machine_signal_type) },
|
||||
#if MICROPY_PY_MACHINE_I2C
|
||||
{ MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&machine_i2c_type) },
|
||||
#endif
|
||||
#if MICROPY_PY_MACHINE_SPI
|
||||
{ MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&mp_machine_soft_spi_type) },
|
||||
#endif
|
||||
#if MICROPY_PY_MACHINE_UART
|
||||
{ MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&machine_uart_type) },
|
||||
#endif
|
||||
#if MICROPY_PY_MACHINE_RTC
|
||||
{ MP_ROM_QSTR(MP_QSTR_RTC), MP_ROM_PTR(&machine_rtc_type) },
|
||||
#endif
|
||||
#if MICROPY_PY_MACHINE_LCD
|
||||
{ MP_ROM_QSTR(MP_QSTR_LCD), MP_ROM_PTR(&machine_lcd_type ) },
|
||||
#endif
|
||||
#if MICROPY_PY_MACHINE_PWM
|
||||
{ MP_ROM_QSTR(MP_QSTR_PWM), MP_ROM_PTR(&machine_pwm_type) },
|
||||
#endif
|
||||
#if MICROPY_PY_MACHINE_ADC
|
||||
{ MP_ROM_QSTR(MP_QSTR_ADC), MP_ROM_PTR(&machine_adc_type) },
|
||||
#endif
|
||||
#if MICROPY_PY_MACHINE_WDT
|
||||
{ MP_ROM_QSTR(MP_QSTR_WDT), MP_ROM_PTR(&machine_wdt_type) },
|
||||
#endif
|
||||
#if MICROPY_PY_MACHINE_TIMER
|
||||
{ MP_ROM_QSTR(MP_QSTR_Timer), MP_ROM_PTR(&machine_timer_type) },
|
||||
#endif
|
||||
};
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(machine_module_globals, machine_module_globals_table);
|
||||
|
||||
const mp_obj_module_t mp_module_machine = {
|
||||
.base = { &mp_type_module },
|
||||
.globals = (mp_obj_dict_t*)&machine_module_globals,
|
||||
};
|
||||
|
||||
#endif // MICROPY_PY_MACHINE
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Armink (armink.ztl@gmail.com)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _MODMACHINE_H
|
||||
#define _MODMACHINE_H
|
||||
|
||||
#include "py/obj.h"
|
||||
#include <rtthread.h>
|
||||
|
||||
extern const mp_obj_type_t machine_pin_type;
|
||||
|
||||
MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(machine_info_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_0(machine_unique_id_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_0(machine_reset_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_0(machine_bootloader_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_0(machine_freq_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_0(pyb_wfi_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_0(pyb_disable_irq_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_enable_irq_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_0(machine_sleep_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_0(machine_deepsleep_obj);
|
||||
|
||||
typedef struct _machine_pin_obj_t {
|
||||
mp_obj_base_t base;
|
||||
char name[RT_NAME_MAX];
|
||||
uint32_t pin;
|
||||
mp_obj_t pin_isr_cb;
|
||||
} machine_pin_obj_t;
|
||||
|
||||
#endif // _MODMACHINE_H
|
||||
Reference in New Issue
Block a user