Просмотр исходного кода

Merge branch 'master' into pwm

ChenYong 6 лет назад
Родитель
Сommit
19cf15dd35

+ 71 - 0
docs/04-Hardware_Control_Module/06-machine-LCD.md

@@ -0,0 +1,71 @@
+## machine.LCD
+
+**machine.LCD** 类是 machine 模块下面的一个硬件类,用于对 LCD 的配置和控制,提供对 LCD 设备的操作方法。
+
+IoT board 板载一块 1.3 寸,分辨率为 `240*240` 的 LCD 显示屏,因此对该屏幕操作时,(x, y)  坐标的范围是 `0 - 239`。
+
+### 构造函数
+
+在 RT-Thread MicroPython 中 `LCD` 对象的构造函数如下:
+
+#### **class machine.LCD**()
+在给定总线上构造一个 `LCD` 对象,无入参,初始化的对象取决于特定硬件,初始化方式可参考 [示例](#_3)。
+
+### 方法
+
+#### **LCD.light**(value)
+
+控制是否开启 LCD 背光,入参为 True 则打开 LCD 背光,入参为 False 则关闭 LCD 背光。
+
+#### **LCD.fill**(color)
+
+根据给定的颜色填充整个屏幕,支持多种颜色,可以传入的参数有:
+
+```
+WHITE BLACK BLUE BRED GRED GBLUE RED MAGENTA GREEN CYAN YELLOW BROWN BRRED GRAY GRAY175 GRAY151 GRAY240
+```
+
+详细的使用方法可参考[示例](#_3)。
+
+#### **LCD.pixel**(x, y, color)
+
+向指定的位置(x, y)画点,点的颜色为 color 指定的颜色,可指定的颜色和上一个功能相同。
+
+注意:(x, y)  坐标的范围是 0 - 239,使用下面的方法对坐标进行操作时同样需要遵循此限制。
+
+#### **LCD.text**(str, x, y, size)
+
+在指定的位置(x,y)写入字符串,字符串由 str 指定,字体的大小由 size 指定,size 的大小可为 16,24,32。
+
+#### **LCD.line**(x1, y1, x2, y2)
+
+在 LCD 上画一条直线,起始地址为 (x1, y1),终点为(x2, y2)。
+
+#### **LCD.rectangle**(x1, y1, x2, y2)
+
+在 LCD 上画一个矩形,左上角的位置为(x1, y1),右下角的位置为(x2, y2)。
+
+#### **LCD.circle**(x1, y1, r)
+
+在 LCD 上画一个圆形,圆心的位置为(x1, y1),半径长度为 r。
+
+### 示例
+
+```python
+from machine import LCD     # 从 machine 导入 LCD 类
+lcd = LCD()                 # 创建一个 lcd 对象
+lcd.light(False)            # 关闭背光
+lcd.light(True)             # 打开背光
+lcd.fill(lcd.BLACK)         # 将整个 LCD 填充为黑色
+lcd.fill(lcd.RED)           # 将整个 LCD 填充为红色
+lcd.fill(lcd.GRAY)          # 将整个 LCD 填充为灰色
+lcd.fill(lcd.WHITE)         # 将整个 LCD 填充为白色
+lcd.pixel(50, 50, lcd.BLUE) # 将(50,50)位置的像素填充为蓝色
+lcd.text("hello RT-Thread", 0, 0, 16)   # 在(0, 0) 位置以 16 字号打印字符串
+lcd.text("hello RT-Thread", 0, 16, 24)  # 在(0, 16)位置以 24 字号打印字符串
+lcd.text("hello RT-Thread", 0, 48, 32)  # 在(0, 48)位置以 32 字号打印字符串
+lcd.line(0, 50, 239, 50)    # 以起点(0,50),终点(239,50)画一条线
+lcd.line(0, 50, 239, 50)    # 以起点(0,50),终点(239,50)画一条线
+lcd.rectangle(100, 100, 200, 200) # 以左上角为(100,100),右下角(200,200)画矩形
+lcd.circle(150, 150, 80)    # 以圆心位置(150,150),半径为 80 画圆
+```

+ 56 - 0
docs/04-Hardware_Control_Module/07-machine-RTC.md

@@ -0,0 +1,56 @@
+## machine.RTC
+
+**machine.RTC** 类是 machine 模块下面的一个硬件类,用于对指定 RTC 设备的配置和控制,提供对 RTC 设备的操作方法。
+
+- RTC(Real-Time Clock )实时时钟可以提供精确的实时时间,它可以用于产生年、月、日、时、分、秒等信息。
+
+### 构造函数
+
+在 RT-Thread MicroPython 中 `RTC` 对象的构造函数如下:
+
+#### **class machine.RTC**()
+
+所以在给定的总线上构造一个 `RTC` 对象,无入参对象,使用方式可参考 [示例](#_3)。 
+
+### 方法
+
+#### **RTC.init**(datetime)
+
+根据传入的参数初始化 RTC 设备起始时间。入参 `datetime` 为一个时间元组,格式如下:
+
+```
+(year, month, day, wday, hour, minute, second, yday)
+```
+参数介绍如下所示:
+
+- **year**:年份;
+- **month**:月份,范围 [1, 12];
+- **day**:日期,范围 [1, 31];
+- **wday**:星期,范围 [0, 6],0 表示星期一,以此类推;
+- **hour**:小时,范围 [0, 23];
+- **minute**:分钟,范围[0, 59];
+- **second**:秒,范围[0, 59];
+- **yday**:从当前年份 1 月 1 日开始的天数,范围 [0, 365],一般置位 0 未实现。
+
+使用的方式可参考 [示例](#_3)。
+
+#### **RTC.deinit**()
+
+重置 RTC 设备时间到 2015 年 1 月 1日,重新运行 RTC 设备。
+
+#### **RTC.now**()
+
+获取当前时间,返回值为上述 `datetime` 时间元组格式。
+
+### 示例
+
+```python
+>>> from machine import RTC
+>>> rtc = RTC()                        # 创建 RTC 设备对象
+>>> rtc.init((2019,6,5,2,10,22,30,0))  # 设置初始化时间
+>>> rtc.now()                          # 获取当前时间
+(2019, 6, 5, 2, 10, 22, 40, 0)
+>>> rtc.deinit()                       # 重置时间到2015年1月1日
+>>> rtc.now()                          # 获取当前时间
+(2015, 1, 1, 3, 0, 0, 1, 0)
+```

+ 9 - 0
docs/07-Network_Module/02-network.md

@@ -0,0 +1,9 @@
+## network – 网络配置
+
+此模块提供网络驱动程序和路由配置。特定硬件的网络驱动程序在此模块中可用,用于配置硬件网络接口。然后,配置接口提供的网络服务可以通过 `usocket` 模块使用。
+
+### 专用的网络类配置
+
+下面具体的类实现了抽象网卡的接口,并提供了一种控制各种网络接口的方法。
+
+- [class WLAN – control built-in WiFi interfaces](./03-network-WLAN.md)

+ 109 - 0
docs/07-Network_Module/03-network-WLAN.md

@@ -0,0 +1,109 @@
+## class WLAN – 控制内置的 WiFi 网络接口
+
+该类为 WiFi 网络处理器提供一个驱动程序。使用示例:
+
+```python
+import network
+# enable station interface and connect to WiFi access point
+nic = network.WLAN(network.STA_IF)
+nic.active(True)
+nic.connect('your-ssid', 'your-password')
+# now use sockets as usual
+```
+
+### 构造函数
+
+在 RT-Thread MicroPython 中 `WLAN` 对象的构造函数如下:
+
+#### class network.WLAN(interface_id)
+
+创建一个 WLAN 网络接口对象。支持的接口是 ` network.STA_IF`(STA 模式,可以连接到上游的 WiFi 热点上) 和 `network.AP_IF`(AP 模式,允许其他 WiFi 客户端连接到自身的热点)。下面方法的可用性取决于接口的类型。例如,只有STA 接口可以使用 `WLAN.connect()`  方法连接到 AP 热点上。
+
+### 方法
+
+#### **WLAN.active**([is_active])
+
+如果向该方法传入布尔数值,传入 True 则使能卡,传入 False 则禁止网卡。否则,如果不传入参数,则查询当前网卡的状态。
+
+#### **WLAN.connect**(ssid, password)
+使用指定的账号和密码链接指定的无线热点。
+
+#### **WLAN.disconnect**()
+从当前链接的无线网络中断开。
+
+#### **WLAN.scan**()
+
+扫描当前可以连接的无线网络。
+
+只能在 STA 模式下进行扫描,使用元组列表的形式返回 WiFi 接入点的相关信息。
+
+(ssid, bssid, channel, rssi, authmode, hidden)
+
+#### **WLAN.status**([param])
+
+返回当前无线连接的状态。
+
+当调用该方法时没有附带参数,就会返回值描述当前网络连接的状态。如果还没有从热点连接中获得 IP 地址,此时的状态为 `STATION_IDLE`。如果已经从连接的无线网络中获得 IP 地址,此时的状态为 `STAT_GOT_IP`。
+
+当调用该函数使用的参数为 `rssi` 时,则返回 `rssi` 的值,该函数目前只支持这一个参数。
+
+#### **WLAN.isconnected**()
+
+在 STA 模式时,如果已经连接到 WiFi 网络,并且获得了 IP 地址,则返回 True。如果处在 AP 模式,此时已经与客户端建立连接,则返回 True。其他情况下都返回 False。
+
+#### WLAN.ifconfig([(ip, subnet, gateway, dns)])
+
+获取或者设置网络接口的参数,IP 地址,子网掩码,网关,DNS 服务器。当调用该方法不附带参数时,该方法会返回一个包含四个元素的元组来描述上面的信息。想要设置上面的值,传入一个包含上述四个元素的元组,例如:
+
+```
+nic.ifconfig(('192.168.0.4', '255.255.255.0', '192.168.0.1', '8.8.8.8'))
+```
+
+#### **WLAN.config**('param')
+
+#### WLAN.config(param=value, ...)
+
+获取或者设置一般网络接口参数,这些方法允许处理标准的 ip 配置之外的其他参数,如 `WLAN. ifconfig()` 函数处理的参数。这些参数包括特定网络和特定硬件的参数。对于参数的设置,应该使用关键字的语法,可以一次性设置多个参数。
+
+当查询参数时,参数名称的引用应该为字符串,且每次只能查询一个参数。
+
+```python
+# Set WiFi access point name (formally known as ESSID) and WiFi password
+ap.config(essid='My_AP', password="88888888")
+# Query params one by one
+print(ap.config('essid'))
+print(ap.config('channel'))
+```
+下面是目前支持的参数:
+
+| Parameter | Description                       |
+| --------- | --------------------------------- |
+| mac       | MAC address (bytes)               |
+| essid     | WiFi access point name (string)   |
+| channel   | WiFi channel (integer)            |
+| hidden    | Whether ESSID is hidden (boolean) |
+| password  | Access password (string)          |
+
+
+### 示例
+
+STA 模式下:
+
+```python
+import network
+wlan = network.WLAN(network.STA_IF)
+wlan.scan()
+wlan.connect("rtthread","02188888888")
+wlan.isconnected()
+```
+
+AP 模式下:
+
+```python
+import network
+ap = network.WLAN(network.AP_IF)
+ap.config(essid="hello_rt-thread", password="88888888")
+ap.active(True)
+ap.config("essid")
+```
+

+ 55 - 1
port/genhdr/qstrdefs.generated.h

@@ -700,5 +700,59 @@ QDEF(MP_QSTR_ffivar, (const byte*)"\x49\x06" "ffivar")
 QDEF(MP_QSTR_channel, (const byte*)"\x26\x07" "channel")
 QDEF(MP_QSTR_channel, (const byte*)"\x26\x07" "channel")
 QDEF(MP_QSTR_duty, (const byte*)"\x19\x04" "duty")
 QDEF(MP_QSTR_duty, (const byte*)"\x19\x04" "duty")
 QDEF(MP_QSTR_PWM, (const byte*)"\x4f\x03" "PWM")
 QDEF(MP_QSTR_PWM, (const byte*)"\x4f\x03" "PWM")
-
+QDEF(MP_QSTR_network, (const byte*)"\x5b\x07" "network")
+QDEF(MP_QSTR_isconnected, (const byte*)"\x80\x0b" "isconnected")
+QDEF(MP_QSTR_WLAN, (const byte*)"\x11\x04" "WLAN")
+QDEF(MP_QSTR_disconnect, (const byte*)"\xa5\x0a" "disconnect")
+QDEF(MP_QSTR_active, (const byte*)"\x69\x06" "active")
+QDEF(MP_QSTR_STA_IF, (const byte*)"\xb3\x06" "STA_IF")
+QDEF(MP_QSTR_AP_IF, (const byte*)"\x04\x05" "AP_IF")
+QDEF(MP_QSTR_bssid, (const byte*)"\x4a\x05" "bssid")
+QDEF(MP_QSTR_status, (const byte*)"\x71\x06" "status")
+QDEF(MP_QSTR_rssi, (const byte*)"\x7e\x04" "rssi")
+QDEF(MP_QSTR_config, (const byte*)"\x4f\x06" "config")
+QDEF(MP_QSTR_ifconfig, (const byte*)"\xe0\x08" "ifconfig")
+QDEF(MP_QSTR_mac, (const byte*)"\xaa\x03" "mac")
+QDEF(MP_QSTR_essid, (const byte*)"\x4d\x05" "essid")
+QDEF(MP_QSTR_hidden, (const byte*)"\xef\x06" "hidden")
+QDEF(MP_QSTR_authmode, (const byte*)"\xce\x08" "authmode")
+QDEF(MP_QSTR_channel, (const byte*)"\x26\x07" "channel")
+QDEF(MP_QSTR_dhcp_hostname, (const byte*)"\xa2\x0d" "dhcp_hostname")
+QDEF(MP_QSTR_STAT_GOT_IP, (const byte*)"\xb2\x0b" "STAT_GOT_IP")
+QDEF(MP_QSTR_STAT_CONNECT_FAIL, (const byte*)"\x0b\x11" "STAT_CONNECT_FAIL")
+QDEF(MP_QSTR_STAT_NO_AP_FOUND, (const byte*)"\xee\x10" "STAT_NO_AP_FOUND")
+QDEF(MP_QSTR_STAT_WRONG_PASSWORD, (const byte*)"\x0b\x13" "STAT_WRONG_PASSWORD")
+QDEF(MP_QSTR_STAT_CONNECTING, (const byte*)"\xf6\x0f" "STAT_CONNECTING")
+QDEF(MP_QSTR_STAT_IDLE, (const byte*)"\x0c\x09" "STAT_IDLE")
+QDEF(MP_QSTR_now, (const byte*)"\xb3\x03" "now")
+QDEF(MP_QSTR_RTC, (const byte*)"\xa0\x03" "RTC")
+QDEF(MP_QSTR_command, (const byte*)"\x02\x07" "command")
+QDEF(MP_QSTR_contrast, (const byte*)"\x07\x08" "contrast")
+QDEF(MP_QSTR_light, (const byte*)"\xfb\x05" "light")
+QDEF(MP_QSTR_fill, (const byte*)"\xca\x04" "fill")
+QDEF(MP_QSTR_pixel, (const byte*)"\x4d\x05" "pixel")
+QDEF(MP_QSTR_show, (const byte*)"\x86\x04" "show")
+QDEF(MP_QSTR_LCD, (const byte*)"\xce\x03" "LCD")
+QDEF(MP_QSTR_text, (const byte*)"\x98\x04" "text")
+QDEF(MP_QSTR_WHITE, (const byte*)"\xa2\x05" "WHITE")
+QDEF(MP_QSTR_BLACK, (const byte*)"\x82\x05" "BLACK")
+QDEF(MP_QSTR_BLUE, (const byte*)"\x3b\x04" "BLUE")
+QDEF(MP_QSTR_BRED, (const byte*)"\x34\x04" "BRED")
+QDEF(MP_QSTR_GRED, (const byte*)"\x91\x04" "GRED")
+QDEF(MP_QSTR_GBLUE, (const byte*)"\x5c\x05" "GBLUE")
+QDEF(MP_QSTR_RED, (const byte*)"\x96\x03" "RED")
+QDEF(MP_QSTR_MAGENTA, (const byte*)"\xf0\x07" "MAGENTA")
+QDEF(MP_QSTR_GREEN, (const byte*)"\xde\x05" "GREEN")
+QDEF(MP_QSTR_CYAN, (const byte*)"\x10\x04" "CYAN")
+QDEF(MP_QSTR_YELLOW, (const byte*)"\x41\x06" "YELLOW")
+QDEF(MP_QSTR_BROWN, (const byte*)"\xc3\x05" "BROWN")
+QDEF(MP_QSTR_BRRED, (const byte*)"\x06\x05" "BRRED")
+QDEF(MP_QSTR_GRAY, (const byte*)"\x08\x04" "GRAY")
+QDEF(MP_QSTR_GRAY175, (const byte*)"\x1b\x07" "GRAY175")
+QDEF(MP_QSTR_GRAY151, (const byte*)"\xdd\x07" "GRAY151")
+QDEF(MP_QSTR_GRAY187, (const byte*)"\xb6\x07" "GRAY187")
+QDEF(MP_QSTR_GRAY240, (const byte*)"\x3e\x07" "GRAY240")
+QDEF(MP_QSTR_line, (const byte*)"\xcb\x04" "line")
+QDEF(MP_QSTR_rectangle, (const byte*)"\xa4\x09" "rectangle")
+QDEF(MP_QSTR_circle, (const byte*)"\xb7\x06" "circle")
 // This file was automatically generated by makeqstrdata.py
 // This file was automatically generated by makeqstrdata.py

+ 233 - 0
port/machine_lcd.c

@@ -0,0 +1,233 @@
+/*
+ * 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"
+
+#if MICROPY_PY_MACHINE_LCD
+
+#include "machine_lcd.h"
+#include <drv_lcd.h>
+
+#define MAX_CO (240 - 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) {
+    machine_lcd_obj_t *self = MP_OBJ_TO_PTR(self_in);
+    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) {
+    machine_lcd_obj_t *self = MP_OBJ_TO_PTR(self_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) {
+    machine_lcd_obj_t *self = MP_OBJ_TO_PTR(args[0]);
+    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) {
+    // extract arguments
+    machine_lcd_obj_t *self = MP_OBJ_TO_PTR(args[0]);
+    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) {
+    // extract arguments
+    machine_lcd_obj_t *self = MP_OBJ_TO_PTR(args[0]);
+
+    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) {
+    // extract arguments
+    machine_lcd_obj_t *self = MP_OBJ_TO_PTR(args[0]);
+
+    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) {
+    // extract arguments
+    machine_lcd_obj_t *self = MP_OBJ_TO_PTR(args[0]);
+
+    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);
+
+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) }, 
+    // 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

+ 31 - 0
port/machine_lcd.h

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

+ 155 - 0
port/machine_rtc.c

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

+ 35 - 0
port/machine_rtc.h

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

+ 10 - 3
port/modmachine.c

@@ -39,6 +39,8 @@
 #include "modmachine.h"
 #include "modmachine.h"
 #include "machine_uart.h"
 #include "machine_uart.h"
 #include "machine_pwm.h"
 #include "machine_pwm.h"
+#include "machine_lcd.h"
+#include "machine_rtc.h"
 
 
 #include <rthw.h>
 #include <rthw.h>
 
 
@@ -177,9 +179,8 @@ STATIC mp_obj_t machine_reset_cause(void) {
 }
 }
 STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_reset_cause_obj, machine_reset_cause);
 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[] = {
 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___name__),            MP_ROM_QSTR(MP_QSTR_umachine) },
     { MP_ROM_QSTR(MP_QSTR_info),                MP_ROM_PTR(&machine_info_obj) },
     { MP_ROM_QSTR(MP_QSTR_info),                MP_ROM_PTR(&machine_info_obj) },
     { MP_ROM_QSTR(MP_QSTR_unique_id),           MP_ROM_PTR(&machine_unique_id_obj) },
     { MP_ROM_QSTR(MP_QSTR_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_reset),               MP_ROM_PTR(&machine_reset_obj) },
@@ -203,7 +204,13 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = {
     { MP_ROM_QSTR(MP_QSTR_SPI),                 MP_ROM_PTR(&mp_machine_soft_spi_type) },
     { MP_ROM_QSTR(MP_QSTR_SPI),                 MP_ROM_PTR(&mp_machine_soft_spi_type) },
 #endif
 #endif
 #if MICROPY_PY_MACHINE_UART
 #if MICROPY_PY_MACHINE_UART
-    { MP_ROM_QSTR(MP_QSTR_UART),                MP_ROM_PTR(&machine_uart_type ) },
+    { 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
 #endif
 #if MICROPY_PY_MACHINE_PWM
 #if MICROPY_PY_MACHINE_PWM
     { MP_ROM_QSTR(MP_QSTR_PWM),                 MP_ROM_PTR(&machine_pwm_type) },
     { MP_ROM_QSTR(MP_QSTR_PWM),                 MP_ROM_PTR(&machine_pwm_type) },

+ 8 - 45
port/modnetwork.c

@@ -30,57 +30,20 @@
 
 
 #include "py/objlist.h"
 #include "py/objlist.h"
 #include "py/runtime.h"
 #include "py/runtime.h"
+#include "py/mphal.h"
+#include "lib/netutils/netutils.h"
 #include "modnetwork.h"
 #include "modnetwork.h"
 
 
 #if MICROPY_PY_NETWORK
 #if MICROPY_PY_NETWORK
 
 
-/// \module network - network configuration
-///
-/// This module provides network drivers and routing configuration.
-
-void mod_network_init(void) {
-    mp_obj_list_init(&MP_STATE_PORT(mod_network_nic_list), 0);
-}
-
-void mod_network_register_nic(mp_obj_t nic) {
-    for (mp_uint_t i = 0; i < MP_STATE_PORT(mod_network_nic_list).len; i++) {
-        if (MP_STATE_PORT(mod_network_nic_list).items[i] == nic) {
-            // nic already registered
-            return;
-        }
-    }
-    // nic not registered so add to list
-    mp_obj_list_append(&MP_STATE_PORT(mod_network_nic_list), nic);
-}
-
-mp_obj_t mod_network_find_nic(const uint8_t *ip) {
-    // find a NIC that is suited to given IP address
-    for (mp_uint_t i = 0; i < MP_STATE_PORT(mod_network_nic_list).len; i++) {
-        mp_obj_t nic = MP_STATE_PORT(mod_network_nic_list).items[i];
-        // TODO check IP suitability here
-        //mod_network_nic_type_t *nic_type = (mod_network_nic_type_t*)mp_obj_get_type(nic);
-        return nic;
-    }
-
-    nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "no available NIC"));
-}
-
-STATIC mp_obj_t network_route(void) {
-    return &MP_STATE_PORT(mod_network_nic_list);
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_0(network_route_obj, network_route);
-
 STATIC const mp_rom_map_elem_t mp_module_network_globals_table[] = {
 STATIC const mp_rom_map_elem_t mp_module_network_globals_table[] = {
     { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_network) },
     { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_network) },
-
-    #if MICROPY_PY_WIZNET5K
-    { MP_ROM_QSTR(MP_QSTR_WIZNET5K), MP_ROM_PTR(&mod_network_nic_type_wiznet5k) },
-    #endif
-    #if MICROPY_PY_CC3K
-    { MP_ROM_QSTR(MP_QSTR_CC3K), MP_ROM_PTR(&mod_network_nic_type_cc3k) },
-    #endif
-
-    { MP_ROM_QSTR(MP_QSTR_route), MP_ROM_PTR(&network_route_obj) },
+    
+#if defined(MICROPY_PY_WLAN)
+    { MP_ROM_QSTR(MP_QSTR_WLAN), MP_ROM_PTR(&get_wlan_obj) },
+    { MP_ROM_QSTR(MP_QSTR_STA_IF), MP_ROM_INT(STATION_IF)},
+    { MP_ROM_QSTR(MP_QSTR_AP_IF), MP_ROM_INT(SOFTAP_IF)},
+#endif
 };
 };
 
 
 STATIC MP_DEFINE_CONST_DICT(mp_module_network_globals, mp_module_network_globals_table);
 STATIC MP_DEFINE_CONST_DICT(mp_module_network_globals, mp_module_network_globals_table);

+ 7 - 54
port/modnetwork.h

@@ -23,61 +23,14 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  * THE SOFTWARE.
  */
  */
-#ifndef MICROPY_INCLUDED_STMHAL_MODNETWORK_H
-#define MICROPY_INCLUDED_STMHAL_MODNETWORK_H
+#ifndef MICROPY_INCLUDED_MODNETWORK_H
+#define MICROPY_INCLUDED_MODNETWORK_H
 
 
-#define MOD_NETWORK_IPADDR_BUF_SIZE (4)
+#define STATION_IF   0
+#define SOFTAP_IF    1
 
 
-#define MOD_NETWORK_AF_INET (2)
-#define MOD_NETWORK_AF_INET6 (10)
+#define MODNETWORK_INCLUDE_CONSTANTS (1)
 
 
-#define MOD_NETWORK_SOCK_STREAM (1)
-#define MOD_NETWORK_SOCK_DGRAM (2)
-#define MOD_NETWORK_SOCK_RAW (3)
+MP_DECLARE_CONST_FUN_OBJ_KW(get_wlan_obj);
 
 
-struct _mod_network_socket_obj_t;
-
-typedef struct _mod_network_nic_type_t {
-    mp_obj_type_t base;
-
-    // API for non-socket operations
-    int (*gethostbyname)(mp_obj_t nic, const char *name, mp_uint_t len, uint8_t *ip_out);
-
-    // API for socket operations; return -1 on error
-    int (*socket)(struct _mod_network_socket_obj_t *socket, int *_errno);
-    void (*close)(struct _mod_network_socket_obj_t *socket);
-    int (*bind)(struct _mod_network_socket_obj_t *socket, byte *ip, mp_uint_t port, int *_errno);
-    int (*listen)(struct _mod_network_socket_obj_t *socket, mp_int_t backlog, int *_errno);
-    int (*accept)(struct _mod_network_socket_obj_t *socket, struct _mod_network_socket_obj_t *socket2, byte *ip, mp_uint_t *port, int *_errno);
-    int (*connect)(struct _mod_network_socket_obj_t *socket, byte *ip, mp_uint_t port, int *_errno);
-    mp_uint_t (*send)(struct _mod_network_socket_obj_t *socket, const byte *buf, mp_uint_t len, int *_errno);
-    mp_uint_t (*recv)(struct _mod_network_socket_obj_t *socket, byte *buf, mp_uint_t len, int *_errno);
-    mp_uint_t (*sendto)(struct _mod_network_socket_obj_t *socket, const byte *buf, mp_uint_t len, byte *ip, mp_uint_t port, int *_errno);
-    mp_uint_t (*recvfrom)(struct _mod_network_socket_obj_t *socket, byte *buf, mp_uint_t len, byte *ip, mp_uint_t *port, int *_errno);
-    int (*setsockopt)(struct _mod_network_socket_obj_t *socket, mp_uint_t level, mp_uint_t opt, const void *optval, mp_uint_t optlen, int *_errno);
-    int (*settimeout)(struct _mod_network_socket_obj_t *socket, mp_uint_t timeout_ms, int *_errno);
-    int (*ioctl)(struct _mod_network_socket_obj_t *socket, mp_uint_t request, mp_uint_t arg, int *_errno);
-} mod_network_nic_type_t;
-
-typedef struct _mod_network_socket_obj_t {
-    mp_obj_base_t base;
-    mp_obj_t nic;
-    mod_network_nic_type_t *nic_type;
-    union {
-        struct {
-            uint8_t domain;
-            uint8_t type;
-            int8_t fileno;
-        } u_param;
-        mp_uint_t u_state;
-    };
-} mod_network_socket_obj_t;
-
-extern const mod_network_nic_type_t mod_network_nic_type_wiznet5k;
-extern const mod_network_nic_type_t mod_network_nic_type_cc3k;
-
-void mod_network_init(void);
-void mod_network_register_nic(mp_obj_t nic);
-mp_obj_t mod_network_find_nic(const uint8_t *ip);
-
-#endif // MICROPY_INCLUDED_STMHAL_MODNETWORK_H
+#endif // MICROPY_INCLUDED_MODNETWORK_H

+ 25 - 0
port/mpconfigport.h

@@ -143,10 +143,19 @@
 #define MICROPY_PY_MACHINE_UART      (1)
 #define MICROPY_PY_MACHINE_UART      (1)
 #endif
 #endif
 
 
+
 #ifdef MICROPYTHON_USING_MACHINE_PWM
 #ifdef MICROPYTHON_USING_MACHINE_PWM
 #define MICROPY_PY_MACHINE_PWM       (1)
 #define MICROPY_PY_MACHINE_PWM       (1)
 #endif
 #endif
 
 
+#ifdef MICROPYTHON_USING_MACHINE_LCD
+#define MICROPY_PY_MACHINE_LCD       (1)
+#endif
+
+#ifdef MICROPYTHON_USING_MACHINE_RTC
+#define MICROPY_PY_MACHINE_RTC       (1)
+#endif
+
 /*****************************************************************************/
 /*****************************************************************************/
 /* System Module                                                             */
 /* System Module                                                             */
 
 
@@ -235,6 +244,14 @@
 #define MICROPY_SSL_MBEDTLS         (1)
 #define MICROPY_SSL_MBEDTLS         (1)
 #endif
 #endif
 
 
+#ifdef MICROPYTHON_USING_NETWORK
+#define MICROPY_PY_NETWORK          (1)
+#endif
+
+#ifdef MICROPYTHON_USING_WLAN
+#define MICROPY_PY_WLAN             (1)
+#endif
+
 #if MICROPY_PY_THREAD
 #if MICROPY_PY_THREAD
 #define MICROPY_EVENT_POLL_HOOK \
 #define MICROPY_EVENT_POLL_HOOK \
     do { \
     do { \
@@ -323,6 +340,7 @@ extern const struct _mp_obj_module_t mp_module_usocket;
 extern const struct _mp_obj_module_t mp_module_io;
 extern const struct _mp_obj_module_t mp_module_io;
 extern const struct _mp_obj_fun_builtin_fixed_t machine_soft_reset_obj;
 extern const struct _mp_obj_fun_builtin_fixed_t machine_soft_reset_obj;
 extern const struct _mp_obj_module_t mp_module_ffi;
 extern const struct _mp_obj_module_t mp_module_ffi;
+extern const struct _mp_obj_module_t mp_module_network;
 
 
 #if MICROPY_PY_RTTHREAD
 #if MICROPY_PY_RTTHREAD
 #define RTTHREAD_PORT_BUILTIN_MODULES { MP_ROM_QSTR(MP_QSTR_rtthread), MP_ROM_PTR(&mp_module_rtthread) },
 #define RTTHREAD_PORT_BUILTIN_MODULES { MP_ROM_QSTR(MP_QSTR_rtthread), MP_ROM_PTR(&mp_module_rtthread) },
@@ -441,6 +459,12 @@ extern const struct _mp_obj_module_t mp_module_ffi;
 #define MODFFI_PORT_BUILTIN_MODULES
 #define MODFFI_PORT_BUILTIN_MODULES
 #endif
 #endif
 
 
+#if MICROPY_PY_NETWORK
+#define MODNETWORK_PORT_BUILTIN_MODULES                    { MP_ROM_QSTR(MP_QSTR_network), MP_ROM_PTR(&mp_module_network) },
+#else
+#define MODNETWORK_PORT_BUILTIN_MODULES
+#endif
+
 // extra built in names to add to the global namespace
 // extra built in names to add to the global namespace
 #define MICROPY_PORT_BUILTINS \
 #define MICROPY_PORT_BUILTINS \
     { MP_ROM_QSTR(MP_QSTR_exit), MP_ROM_PTR(&machine_soft_reset_obj) }, \
     { MP_ROM_QSTR(MP_QSTR_exit), MP_ROM_PTR(&machine_soft_reset_obj) }, \
@@ -455,6 +479,7 @@ extern const struct _mp_obj_module_t mp_module_ffi;
     SOCKET_PORT_BUILTIN_MODULES \
     SOCKET_PORT_BUILTIN_MODULES \
     MODUTIME_PORT_BUILTIN_MODULES \
     MODUTIME_PORT_BUILTIN_MODULES \
     MODFFI_PORT_BUILTIN_MODULES \
     MODFFI_PORT_BUILTIN_MODULES \
+    MODNETWORK_PORT_BUILTIN_MODULES \
 
 
 #define MICROPY_PORT_BUILTIN_MODULE_WEAK_LINKS \
 #define MICROPY_PORT_BUILTIN_MODULE_WEAK_LINKS \
     MODUTIME_PORT_BUILTIN_MODULE_WEAK_LINKS \
     MODUTIME_PORT_BUILTIN_MODULE_WEAK_LINKS \

+ 575 - 0
port/network_wlan.c

@@ -0,0 +1,575 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 SummerGift <SummerGift@qq.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+
+#include "py/objlist.h"
+#include "py/runtime.h"
+#include "py/mphal.h"
+#include "lib/netutils/netutils.h"
+
+#if MICROPY_PY_WLAN
+#include <rtthread.h>
+#include <wlan_mgnt.h>
+#include <wlan_cfg.h>
+#include <wlan_prot.h>
+#include <arpa/inet.h>
+#include <netdev.h>     
+#include "modnetwork.h"
+
+extern struct netdev *netdev_default;
+
+typedef struct _wlan_if_obj_t {
+    mp_obj_base_t base;
+    int if_id;
+} wlan_if_obj_t;
+
+enum {
+    STATION_IDLE = 0,
+    STATION_CONNECTING,
+    STATION_WRONG_PASSWORD,
+    STATION_NO_AP_FOUND,
+    STATION_CONNECT_FAIL,
+    STATION_GOT_IP,
+};
+
+const mp_obj_type_t wlan_if_type;
+STATIC struct rt_wlan_info _ap_info;
+STATIC char _ap_password[RT_WLAN_PASSWORD_MAX_LENGTH];
+
+STATIC void error_check(bool status, const char *msg) {
+    if (!status) {
+        nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, msg));
+    }
+}
+
+STATIC const wlan_if_obj_t wlan_objs[] = {
+    {{&wlan_if_type}, STATION_IF},
+    {{&wlan_if_type}, SOFTAP_IF},
+};
+
+STATIC void require_if(mp_obj_t wlan_if, int if_no) {
+    wlan_if_obj_t *self = MP_OBJ_TO_PTR(wlan_if);
+    if (self->if_id != if_no) {
+        error_check(false, if_no == STATION_IF ? "STA required" : "AP required");
+    }
+}
+
+STATIC mp_obj_t get_wlan(size_t n_args, const mp_obj_t *args) {
+    int idx = 0;
+    if (n_args > 0) {
+        idx = mp_obj_get_int(args[0]);
+        if (idx < 0 || idx >= sizeof(wlan_objs)) {
+            mp_raise_ValueError(NULL);
+        }
+    }
+    return MP_OBJ_FROM_PTR(&wlan_objs[idx]);
+}
+MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(get_wlan_obj, 0, 1, get_wlan);
+
+STATIC mp_obj_t wlan_active(size_t n_args, const mp_obj_t *args) {
+
+    wlan_if_obj_t *self = MP_OBJ_TO_PTR(args[0]);
+
+    if (n_args > 1) {
+
+        if (self->if_id == STATION_IF)
+        {
+            if (mp_obj_get_int(args[1]) == RT_TRUE)
+            {
+                error_check(netdev_set_up(netdev_default) == RT_EOK, "Cannot active wlan device");
+            }
+            else
+            {
+                error_check(netdev_set_down(netdev_default) == RT_EOK, "Cannot disable wlan device");
+            }
+        }
+        else
+        {
+            if (mp_obj_get_int(args[1]) == RT_TRUE)
+            {
+                error_check(rt_wlan_start_ap((char *)&_ap_info.ssid.val, _ap_password) == RT_EOK, "Cannot start AP");
+            }
+            else
+            {
+                error_check(rt_wlan_ap_stop() == RT_EOK, "Cannot stop AP");
+            }
+        }
+
+        return mp_const_none;
+    }
+
+    if (self->if_id == STATION_IF)
+    {
+        return mp_obj_new_bool(rt_wlan_get_mode("wlan0") == RT_WLAN_STATION);
+    }
+    else
+    {
+        return mp_obj_new_bool(rt_wlan_get_mode("wlan1") == RT_WLAN_AP);
+    }
+    
+    return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(wlan_active_obj, 1, 2, wlan_active);
+
+STATIC mp_obj_t wlan_connect(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+    enum { ARG_ssid, ARG_password, ARG_bssid };
+    static const mp_arg_t allowed_args[] = {
+        { MP_QSTR_, MP_ARG_OBJ, {.u_obj = mp_const_none} },
+        { MP_QSTR_, MP_ARG_OBJ, {.u_obj = mp_const_none} },
+        { MP_QSTR_bssid, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
+    };
+
+    // parse args
+    mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
+    mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
+
+    require_if(pos_args[0], STATION_IF);
+    
+    const char *ssid = RT_NULL;
+    const char *key = RT_NULL;
+    size_t len;
+    const char *p;
+
+    // set parameters based on given args
+    if (args[ARG_ssid].u_obj != mp_const_none) {
+        p = mp_obj_str_get_data(args[ARG_ssid].u_obj, &len);
+        ssid = p;
+    }
+
+    if (args[ARG_password].u_obj != mp_const_none) {
+        p = mp_obj_str_get_data(args[ARG_password].u_obj, &len);
+        key = p;
+    }
+
+    error_check(rt_wlan_connect(ssid, key) == RT_EOK, "Cannot connect to AP");
+
+    return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_KW(wlan_connect_obj, 1, wlan_connect);
+
+STATIC mp_obj_t wlan_disconnect(mp_obj_t self_in) {
+    require_if(self_in, STATION_IF);
+    error_check(rt_wlan_disconnect() == RT_EOK, "Cannot disconnect from AP");
+    return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(wlan_disconnect_obj, wlan_disconnect);
+
+STATIC mp_obj_t wlan_status(size_t n_args, const mp_obj_t *args) {
+    wlan_if_obj_t *self = MP_OBJ_TO_PTR(args[0]);
+    if (n_args == 1) {
+        // Get link status
+        if (self->if_id == STATION_IF) {
+            
+            if(rt_wlan_is_ready() == RT_EOK)
+            {
+                return MP_OBJ_NEW_SMALL_INT(STATION_GOT_IP);
+            }
+            else
+            {
+                return MP_OBJ_NEW_SMALL_INT(STATION_IDLE);
+            }
+        }
+        return MP_OBJ_NEW_SMALL_INT(-1);
+    } else {
+        // Get specific status parameter
+        switch (mp_obj_str_get_qstr(args[1])) {
+            case MP_QSTR_rssi:
+                if (self->if_id == STATION_IF) {
+                    return MP_OBJ_NEW_SMALL_INT(rt_wlan_get_rssi());
+                }
+        }
+        mp_raise_ValueError("unknown status param");
+    }
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(wlan_status_obj, 1, 2, wlan_status);
+
+STATIC mp_obj_t *wlan_scan_list = NULL;
+
+void wlan_station_scan(void)
+{
+    if (wlan_scan_list == NULL) {
+        // called unexpectedly
+        return;
+    }
+    
+    struct rt_wlan_scan_result *scan_result = RT_NULL;
+
+    /* scan ap info */
+    scan_result = rt_wlan_scan_sync();
+    if (scan_result)
+    {
+        int index, num;
+        char *security;
+
+        num = scan_result->num;
+        for (index = 0; index < num; index ++)
+        {
+            switch (scan_result->info[index].security)
+            {
+            case SECURITY_OPEN:
+                security = "OPEN";
+                break;
+            case SECURITY_WEP_PSK:
+                security = "WEP_PSK";
+                break;
+            case SECURITY_WEP_SHARED:
+                security = "WEP_SHARED";
+                break;
+            case SECURITY_WPA_TKIP_PSK:
+                security = "WPA_TKIP_PSK";
+                break;
+            case SECURITY_WPA_AES_PSK:
+                security = "WPA_AES_PSK";
+                break;
+            case SECURITY_WPA2_AES_PSK:
+                security = "WPA2_AES_PSK";
+                break;
+            case SECURITY_WPA2_TKIP_PSK:
+                security = "WPA2_TKIP_PSK";
+                break;
+            case SECURITY_WPA2_MIXED_PSK:
+                security = "WPA2_MIXED_PSK";
+                break;
+            case SECURITY_WPS_OPEN:
+                security = "WPS_OPEN";
+                break;
+            case SECURITY_WPS_SECURE:
+                security = "WPS_SECURE";
+                break;
+            default:
+                security = "UNKNOWN";
+                break;
+            }
+
+            mp_obj_tuple_t *t = mp_obj_new_tuple(6, NULL);
+            t->items[0] = mp_obj_new_bytes(&scan_result->info[index].ssid.val[0], strlen((char *)(&scan_result->info[index].ssid.val[0])));
+            t->items[1] = mp_obj_new_bytes(&scan_result->info[index].bssid[0], strlen((char *)(&scan_result->info[index].bssid[0])));
+            t->items[2] = MP_OBJ_NEW_SMALL_INT(scan_result->info[index].channel);
+            t->items[3] = MP_OBJ_NEW_SMALL_INT(scan_result->info[index].rssi);
+            t->items[4] = mp_obj_new_bytes((const byte *)security, strlen(security));
+            t->items[5] = MP_OBJ_NEW_SMALL_INT(scan_result->info[index].hidden);
+            
+            mp_obj_list_append(*wlan_scan_list, MP_OBJ_FROM_PTR(t));
+
+        }
+        rt_wlan_scan_result_clean();
+    }
+    else
+    {
+        rt_kprintf("wifi scan result is null\n");
+        *wlan_scan_list = MP_OBJ_NULL;
+    }
+}
+
+STATIC mp_obj_t wlan_scan(mp_obj_t self_in) {
+    require_if(self_in, STATION_IF);
+
+    mp_obj_t list = mp_obj_new_list(0, NULL);
+    wlan_scan_list = &list;
+    wlan_station_scan();
+
+    if (list == MP_OBJ_NULL) {
+        nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "scan failed"));
+    }
+    return list;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(wlan_scan_obj, wlan_scan);
+
+/// \method isconnected()
+/// Return True if connected to an AP and an IP address has been assigned,
+/// false otherwise.
+STATIC mp_obj_t wlan_isconnected(mp_obj_t self_in) {
+    wlan_if_obj_t *self = MP_OBJ_TO_PTR(self_in);
+    if (self->if_id == STATION_IF) {
+        if (rt_wlan_is_connected() == RT_TRUE) {
+            return mp_const_true;
+        }
+    } else {
+        if (rt_wlan_ap_get_sta_num() > 0) {
+            return mp_const_true;
+        }
+    }
+    return mp_const_false;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(wlan_isconnected_obj, wlan_isconnected);
+
+STATIC mp_obj_t wlan_ifconfig(size_t n_args, const mp_obj_t *args) {
+    wlan_if_obj_t *self = MP_OBJ_TO_PTR(args[0]);
+    
+    struct netdev *netdev = netdev_default;
+    if (netdev == RT_NULL)
+    {
+        rt_kprintf("not find wlan interface device.\n");
+        return MP_OBJ_NEW_SMALL_INT(-1);
+    }
+
+    if (n_args == 1) {
+        // get
+        mp_obj_t tuple[4] = {
+            mp_obj_new_str((const char *)inet_ntoa(netdev->ip_addr), strlen((char *)(inet_ntoa(netdev->ip_addr)))),
+            mp_obj_new_str((const char *)inet_ntoa(netdev->netmask), strlen((char *)(inet_ntoa(netdev->netmask)))),
+            mp_obj_new_str((const char *)inet_ntoa(netdev->gw), strlen((char *)(inet_ntoa(netdev->gw)))),
+            mp_obj_new_str((const char *)inet_ntoa(netdev->dns_servers), strlen((char *)(inet_ntoa(netdev->dns_servers)))),
+        };
+        return mp_obj_new_tuple(4, tuple);
+    } 
+    else 
+    {
+        // set
+        mp_obj_t *items;
+        bool restart_dhcp_server = false;
+
+        uint8_t ip_addr[4];
+        uint8_t netmask[4];
+        uint8_t gw[4];
+        uint8_t dns_server[4];
+        
+        mp_obj_get_array_fixed_n(args[1], 4, &items);
+
+        netutils_parse_ipv4_addr(items[0], (uint8_t *)ip_addr,    NETUTILS_BIG);
+        netutils_parse_ipv4_addr(items[1], (uint8_t *)netmask,    NETUTILS_BIG);
+        netutils_parse_ipv4_addr(items[2], (uint8_t *)gw     ,    NETUTILS_BIG);
+        netutils_parse_ipv4_addr(items[3], (uint8_t *)dns_server, NETUTILS_BIG);
+
+        // To set a static IP we have to disable DHCP first
+        if (self->if_id == STATION_IF) {
+            if(netdev_dhcp_enabled(netdev, 0) == RT_EOK)
+            {
+                if (netdev_set_ipaddr(netdev, (const ip_addr_t *)ip_addr) != RT_EOK)
+                {
+                    nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "netdev_set_ipaddr() failed"));         
+                }
+            }
+            else
+            {
+                nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "netdev_dhcp_enabled() failed"));  
+            }
+        }
+        else 
+        {
+            // TODO modify IP netmask gw under AP mode
+            netdev_set_dns_server(netdev, 0, (const ip_addr_t *)dns_server);
+            return mp_const_none;
+        }
+
+        netdev_set_netmask(netdev, (const ip_addr_t *)netmask);
+        netdev_set_gw(netdev, (const ip_addr_t *)gw);
+        netdev_set_dns_server(netdev, 0, (const ip_addr_t *)dns_server);
+    }
+    
+    return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(wlan_ifconfig_obj, 1, 2, wlan_ifconfig);
+
+STATIC mp_obj_t wlan_config(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) {
+    if (n_args != 1 && kwargs->used != 0) {
+        mp_raise_TypeError("either pos or kw args are allowed");
+    }
+
+    wlan_if_obj_t *self = MP_OBJ_TO_PTR(args[0]);
+    struct rt_wlan_info cfg = {0};
+
+    if (self->if_id == STATION_IF) {
+        error_check(rt_wlan_get_info(&cfg) == RT_EOK, "can't get STA config");
+    } else {
+        error_check(rt_wlan_ap_get_info(&cfg) == RT_EOK, "can't get AP config");
+    }
+
+    int req_if = -1;
+
+    if (kwargs->used != 0) {
+
+        for (mp_uint_t i = 0; i < kwargs->alloc; i++) {
+            if (mp_map_slot_is_filled(kwargs, i)) {
+                #define QS(x) (uintptr_t)MP_OBJ_NEW_QSTR(x)
+                switch ((uintptr_t)kwargs->table[i].key) {
+                    case QS(MP_QSTR_mac): {
+                        mp_buffer_info_t bufinfo;
+                        mp_get_buffer_raise(kwargs->table[i].value, &bufinfo, MP_BUFFER_READ);
+                        if (bufinfo.len != 6) {
+                            mp_raise_ValueError("invalid buffer length");
+                        }
+                        error_check(rt_wlan_set_mac((rt_uint8_t *)bufinfo.buf) == RT_EOK, "can't set MAC");
+
+                        break;
+                    }
+                    case QS(MP_QSTR_essid): { 
+                        req_if = SOFTAP_IF;
+                        size_t len;
+                        const char *s = mp_obj_str_get_data(kwargs->table[i].value, &len);
+                        len = MIN(len, sizeof(_ap_info.ssid.val));
+                        memcpy(_ap_info.ssid.val, s, len);
+                        _ap_info.ssid.len = len;
+                        break;
+                    }
+                    case QS(MP_QSTR_hidden): {
+                        req_if = SOFTAP_IF;
+                        _ap_info.hidden = mp_obj_is_true(kwargs->table[i].value);
+                        break;
+                    }
+//                    case QS(MP_QSTR_authmode): {
+//                        req_if = SOFTAP_IF;
+//                        cfg.ap.authmode = mp_obj_get_int(kwargs->table[i].value);
+//                        break;
+//                    }
+                    case QS(MP_QSTR_password): {
+                        req_if = SOFTAP_IF;
+                        size_t len;
+                        const char *s = mp_obj_str_get_data(kwargs->table[i].value, &len);
+                        len = MIN(len, sizeof(_ap_password) - 1);
+                        memcpy(_ap_password, s, len);
+                        _ap_password[len] = 0;
+                        break;
+                    }
+                    case QS(MP_QSTR_channel): {
+                        req_if = SOFTAP_IF;
+                        _ap_info.channel = mp_obj_get_int(kwargs->table[i].value);
+                        break;
+                    }
+//                    case QS(MP_QSTR_dhcp_hostname): {
+//                        req_if = STATION_IF;
+//                        if (self->if_id == STATION_IF) {
+//                            const char *s = mp_obj_str_get_str(kwargs->table[i].value);
+//                            wifi_station_set_hostname((char*)s);
+//                        }
+//                        break;
+//                    }
+                    default:
+                        goto unknown;
+                }
+                #undef QS
+            }
+        }
+
+        // We post-check interface requirements to save on code size
+        if (req_if >= 0) {
+            require_if(args[0], req_if);
+        }
+
+        return mp_const_none;
+    }
+
+    // Get config
+    if (n_args != 2) {
+        mp_raise_TypeError("can query only one param");
+    }
+
+    mp_obj_t val;
+
+    qstr key = mp_obj_str_get_qstr(args[1]);
+    switch (key) {
+        case MP_QSTR_mac: {
+            uint8_t mac[6];
+            error_check(rt_wlan_get_mac(mac) == RT_EOK, "can't get mac config");
+            return mp_obj_new_bytes(mac, sizeof(mac));
+        }
+        case MP_QSTR_essid:
+            if (self->if_id == STATION_IF) {
+                val = mp_obj_new_str((char*)cfg.ssid.val, strlen((char*)cfg.ssid.val));
+            } else {
+                val = mp_obj_new_str((char*)_ap_info.ssid.val, _ap_info.ssid.len);
+            }
+            break;
+        case MP_QSTR_hidden:
+            req_if = SOFTAP_IF;
+            val = mp_obj_new_bool(cfg.hidden);
+            break;
+//        case MP_QSTR_authmode:
+//            req_if = SOFTAP_IF;
+//            val = MP_OBJ_NEW_SMALL_INT(cfg.ap.authmode);
+//            break;
+        case MP_QSTR_channel:
+            req_if = SOFTAP_IF;
+            val = MP_OBJ_NEW_SMALL_INT(cfg.channel);
+            break;
+//        case MP_QSTR_dhcp_hostname: {
+//            req_if = STATION_IF;
+//            char* s = wifi_station_get_hostname();
+//            if (s == NULL) {
+//                val = MP_OBJ_NEW_QSTR(MP_QSTR_);
+//            } else {
+//                val = mp_obj_new_str(s, strlen(s));
+//            }
+//            break;
+//        }
+        default:
+            goto unknown;
+    }
+
+    // We post-check interface requirements to save on code size
+    if (req_if >= 0) {
+        require_if(args[0], req_if);
+    }
+
+    return val;
+
+unknown:
+    mp_raise_ValueError("unknown config param");
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_KW(wlan_config_obj, 1, wlan_config);
+
+STATIC const mp_rom_map_elem_t wlan_if_locals_dict_table[] = {
+    { MP_ROM_QSTR(MP_QSTR_active), MP_ROM_PTR(&wlan_active_obj) },
+    { MP_ROM_QSTR(MP_QSTR_connect), MP_ROM_PTR(&wlan_connect_obj) },
+    { MP_ROM_QSTR(MP_QSTR_disconnect), MP_ROM_PTR(&wlan_disconnect_obj) },
+    { MP_ROM_QSTR(MP_QSTR_status), MP_ROM_PTR(&wlan_status_obj) },
+    { MP_ROM_QSTR(MP_QSTR_scan), MP_ROM_PTR(&wlan_scan_obj) },
+    { MP_ROM_QSTR(MP_QSTR_isconnected), MP_ROM_PTR(&wlan_isconnected_obj) },
+    { MP_ROM_QSTR(MP_QSTR_config), MP_ROM_PTR(&wlan_config_obj) },
+    { MP_ROM_QSTR(MP_QSTR_ifconfig), MP_ROM_PTR(&wlan_ifconfig_obj) },
+    
+#if MODNETWORK_INCLUDE_CONSTANTS
+    { MP_ROM_QSTR(MP_QSTR_STAT_IDLE), MP_ROM_INT(STATION_IDLE)},
+    { MP_ROM_QSTR(MP_QSTR_STAT_CONNECTING), MP_ROM_INT(STATION_CONNECTING)},
+    { MP_ROM_QSTR(MP_QSTR_STAT_WRONG_PASSWORD), MP_ROM_INT(STATION_WRONG_PASSWORD)},
+    { MP_ROM_QSTR(MP_QSTR_STAT_NO_AP_FOUND), MP_ROM_INT(STATION_NO_AP_FOUND)},
+    { MP_ROM_QSTR(MP_QSTR_STAT_CONNECT_FAIL), MP_ROM_INT(STATION_CONNECT_FAIL)},
+    { MP_ROM_QSTR(MP_QSTR_STAT_GOT_IP), MP_ROM_INT(STATION_GOT_IP)},
+
+//    { MP_ROM_QSTR(MP_QSTR_MODE_11B), MP_ROM_INT(PHY_MODE_11B) },
+//    { MP_ROM_QSTR(MP_QSTR_MODE_11G), MP_ROM_INT(PHY_MODE_11G) },
+//    { MP_ROM_QSTR(MP_QSTR_MODE_11N), MP_ROM_INT(PHY_MODE_11N) },
+
+//    { MP_ROM_QSTR(MP_QSTR_AUTH_OPEN), MP_ROM_INT(AUTH_OPEN) },
+//    { MP_ROM_QSTR(MP_QSTR_AUTH_WEP), MP_ROM_INT(AUTH_WEP) },
+//    { MP_ROM_QSTR(MP_QSTR_AUTH_WPA_PSK), MP_ROM_INT(AUTH_WPA_PSK) },
+//    { MP_ROM_QSTR(MP_QSTR_AUTH_WPA2_PSK), MP_ROM_INT(AUTH_WPA2_PSK) },
+//    { MP_ROM_QSTR(MP_QSTR_AUTH_WPA_WPA2_PSK), MP_ROM_INT(AUTH_WPA_WPA2_PSK) },
+#endif
+};
+
+STATIC MP_DEFINE_CONST_DICT(wlan_if_locals_dict, wlan_if_locals_dict_table);
+
+const mp_obj_type_t wlan_if_type = {
+    { &mp_type_type },
+    .name = MP_QSTR_WLAN,
+    .locals_dict = (mp_obj_dict_t*)&wlan_if_locals_dict,
+};
+
+#endif