aboutsummaryrefslogtreecommitdiff
path: root/cc3200/mods
diff options
context:
space:
mode:
authordanicampora2015-02-06 15:35:48 +0100
committerDamien George2015-02-06 22:10:11 +0000
commit8785645a952c03315dbf93667b5f7c7eec49762f (patch)
tree267e2d572d87e92bfc0bfabf83859231152a2162 /cc3200/mods
parent97f14606f528180d1482cffbe3571163a1dd9273 (diff)
cc3200: Add cc3200 port of MicroPython.
The port currently implements support for GPIO, RTC, ExtInt and the WiFi subsystem. A small file system is available in the serial flash. A bootloader which makes OTA updates possible, is also part of this initial implementation.
Diffstat (limited to 'cc3200/mods')
-rw-r--r--cc3200/mods/modnetwork.c152
-rw-r--r--cc3200/mods/modnetwork.h81
-rw-r--r--cc3200/mods/modpyb.c318
-rw-r--r--cc3200/mods/moduos.c337
-rw-r--r--cc3200/mods/modusocket.c451
-rw-r--r--cc3200/mods/modutime.c333
-rw-r--r--cc3200/mods/modutime.h43
-rw-r--r--cc3200/mods/modwlan.c1199
-rw-r--r--cc3200/mods/modwlan.h71
-rw-r--r--cc3200/mods/pybextint.c357
-rw-r--r--cc3200/mods/pybextint.h47
-rw-r--r--cc3200/mods/pybgpio.c529
-rw-r--r--cc3200/mods/pybgpio.h68
-rw-r--r--cc3200/mods/pybrtc.c158
-rw-r--r--cc3200/mods/pybrtc.h33
-rw-r--r--cc3200/mods/pybstdio.c174
-rw-r--r--cc3200/mods/pybstdio.h31
-rw-r--r--cc3200/mods/pybsystick.c93
-rw-r--r--cc3200/mods/pybsystick.h30
-rw-r--r--cc3200/mods/pybuart.c682
-rw-r--r--cc3200/mods/pybuart.h45
21 files changed, 5232 insertions, 0 deletions
diff --git a/cc3200/mods/modnetwork.c b/cc3200/mods/modnetwork.c
new file mode 100644
index 000000000..2e100aecb
--- /dev/null
+++ b/cc3200/mods/modnetwork.c
@@ -0,0 +1,152 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2013, 2014 Damien P. George
+ * Copyright (c) 2015 Daniel Campora
+ *
+ * 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 <std.h>
+#include <stdint.h>
+#include <string.h>
+
+#include "mpconfig.h"
+#include MICROPY_HAL_H
+#include "nlr.h"
+#include "misc.h"
+#include "qstr.h"
+#include "obj.h"
+#include "objlist.h"
+#include "runtime.h"
+#include "modnetwork.h"
+#include "mpexception.h"
+#include "mpstate.h"
+
+/// \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];
+ return nic;
+ }
+
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable));
+}
+
+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_map_elem_t mp_module_network_globals_table[] = {
+ { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_network) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_WLAN), (mp_obj_t)&mod_network_nic_type_wlan },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_route), (mp_obj_t)&network_route_obj },
+};
+
+STATIC MP_DEFINE_CONST_DICT(mp_module_network_globals, mp_module_network_globals_table);
+
+const mp_obj_module_t mp_module_network = {
+ .base = { &mp_type_module },
+ .name = MP_QSTR_network,
+ .globals = (mp_obj_dict_t*)&mp_module_network_globals,
+};
+
+/******************************************************************************/
+// Miscellaneous helpers
+
+void mod_network_convert_ipv4_endianness(uint8_t *ip) {
+ uint8_t ip0 = ip[0]; ip[0] = ip[3]; ip[3] = ip0;
+ uint8_t ip1 = ip[1]; ip[1] = ip[2]; ip[2] = ip1;
+}
+
+// Takes an address of the form '192.168.0.1' and converts it to network format
+// in out_ip (big endian, so the 192 is the first byte).
+void mod_network_parse_ipv4_addr(mp_obj_t addr_in, uint8_t *out_ip) {
+ mp_uint_t addr_len;
+ const char *addr_str = mp_obj_str_get_data(addr_in, &addr_len);
+ if (addr_len == 0) {
+ // special case of no address given
+ memset(out_ip, 0, MOD_NETWORK_IPV4ADDR_BUF_SIZE);
+ return;
+ }
+ const char *s = addr_str;
+ const char *s_top = addr_str + addr_len;
+ for (mp_uint_t i = 0;; i++) {
+ mp_uint_t val = 0;
+ for (; s < s_top && *s != '.'; s++) {
+ val = val * 10 + *s - '0';
+ }
+ out_ip[i] = val;
+ if (i == 3 && s == s_top) {
+ return;
+ } else if (i < 3 && s < s_top && *s == '.') {
+ s++;
+ } else {
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
+ }
+ }
+}
+
+// Takes an address of the form ('192.168.0.1', 8080), returns the port and
+// puts IP in out_ip (which must take at least IPADDR_BUF_SIZE bytes).
+mp_uint_t mod_network_parse_inet_addr(mp_obj_t addr_in, uint8_t *out_ip) {
+ mp_obj_t *addr_items;
+ mp_obj_get_array_fixed_n(addr_in, 2, &addr_items);
+ mod_network_parse_ipv4_addr(addr_items[0], out_ip);
+ return mp_obj_get_int(addr_items[1]);
+}
+
+// Takes an array with a raw IPv4 address and returns something like '192.168.0.1'.
+mp_obj_t mod_network_format_ipv4_addr(uint8_t *ip) {
+ char ip_str[16];
+ mp_uint_t ip_len = snprintf(ip_str, 16, "%u.%u.%u.%u", ip[0], ip[1], ip[2], ip[3]);
+ return mp_obj_new_str(ip_str, ip_len, false);
+}
+
+// Takes an array with a raw IP address, and a port, and returns a net-address
+// tuple such as ('192.168.0.1', 8080).
+mp_obj_t mod_network_format_inet_addr(uint8_t *ip, mp_uint_t port) {
+ mp_obj_t tuple[2] = {
+ tuple[0] = mod_network_format_ipv4_addr(ip),
+ tuple[1] = mp_obj_new_int(port),
+ };
+ return mp_obj_new_tuple(2, tuple);
+}
diff --git a/cc3200/mods/modnetwork.h b/cc3200/mods/modnetwork.h
new file mode 100644
index 000000000..838073395
--- /dev/null
+++ b/cc3200/mods/modnetwork.h
@@ -0,0 +1,81 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2013, 2014 Damien P. George
+ * Copyright (c) 2015 Daniel Campora
+ *
+ * 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.
+ */
+
+#define MOD_NETWORK_IPV4ADDR_BUF_SIZE (4)
+
+// Forward declaration
+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, uint8_t family);
+
+ // API for socket operations; return -1 on error
+ int (*socket)(struct _mod_network_socket_obj_t *s, int *_errno);
+ void (*close)(struct _mod_network_socket_obj_t *socket);
+ int (*bind)(struct _mod_network_socket_obj_t *s, byte *ip, mp_uint_t port, int *_errno);
+ int (*listen)(struct _mod_network_socket_obj_t *s, mp_int_t backlog, int *_errno);
+ int (*accept)(struct _mod_network_socket_obj_t *s, struct _mod_network_socket_obj_t *s2, byte *ip, mp_uint_t *port, int *_errno);
+ int (*connect)(struct _mod_network_socket_obj_t *s, byte *ip, mp_uint_t port, int *_errno);
+ int (*send)(struct _mod_network_socket_obj_t *s, const byte *buf, mp_uint_t len, int *_errno);
+ int (*recv)(struct _mod_network_socket_obj_t *s, byte *buf, mp_uint_t len, int *_errno);
+ int (*sendto)(struct _mod_network_socket_obj_t *s, const byte *buf, mp_uint_t len, byte *ip, mp_uint_t port, int *_errno);
+ int (*recvfrom)(struct _mod_network_socket_obj_t *s, byte *buf, mp_uint_t len, byte *ip, mp_uint_t *port, int *_errno);
+ int (*setsockopt)(struct _mod_network_socket_obj_t *s, 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 *s, mp_uint_t timeout_ms, int *_errno);
+ int (*ioctl)(struct _mod_network_socket_obj_t *s, 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;
+ uint8_t proto;
+ int8_t fileno;
+ } u_param;
+ int16_t sd;
+ bool closed;
+ };
+} mod_network_socket_obj_t;
+
+extern const mod_network_nic_type_t mod_network_nic_type_wlan;
+
+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);
+
+void mod_network_convert_ipv4_endianness(uint8_t *ip);
+void mod_network_parse_ipv4_addr(mp_obj_t addr_in, uint8_t *out_ip);
+mp_uint_t mod_network_parse_inet_addr(mp_obj_t addr_in, uint8_t *out_ip);
+mp_obj_t mod_network_format_ipv4_addr(uint8_t *ip);
+mp_obj_t mod_network_format_inet_addr(uint8_t *ip, mp_uint_t port);
diff --git a/cc3200/mods/modpyb.c b/cc3200/mods/modpyb.c
new file mode 100644
index 000000000..f17d6a257
--- /dev/null
+++ b/cc3200/mods/modpyb.c
@@ -0,0 +1,318 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2013, 2014 Damien P. George
+ * Copyright (c) 2015 Daniel Campora
+ *
+ * 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 <std.h>
+#include <stdint.h>
+
+#include "py/mpstate.h"
+#include "mpconfig.h"
+#include MICROPY_HAL_H
+#include "misc.h"
+#include "nlr.h"
+#include "qstr.h"
+#include "obj.h"
+#include "gc.h"
+#include "gccollect.h"
+#include "irq.h"
+#include "inc/hw_types.h"
+#include "inc/hw_gpio.h"
+#include "inc/hw_ints.h"
+#include "inc/hw_memmap.h"
+#include "inc/hw_uart.h"
+#include "prcm.h"
+#include "pyexec.h"
+#include "pybuart.h"
+#include "pybgpio.h"
+#include "pybstdio.h"
+#include "pybrtc.h"
+#include "pybsystick.h"
+#include "simplelink.h"
+#include "modwlan.h"
+#include "telnet.h"
+#include "ff.h"
+#include "diskio.h"
+#include "sflash_diskio.h"
+#include "FreeRTOS.h"
+#include "portable.h"
+#include "task.h"
+#include "mpexception.h"
+#include "random.h"
+#include "pybextint.h"
+
+
+#ifdef DEBUG
+extern OsiTaskHandle mpTaskHandle;
+extern OsiTaskHandle svTaskHandle;
+extern TaskHandle_t xSimpleLinkSpawnTaskHndl;
+#endif
+
+/// \module pyb - functions related to the pyboard
+///
+/// The `pyb` module contains specific functions related to the pyboard.
+
+/// \function hard_reset()
+/// Resets the pyboard in a manner similar to pushing the external RESET
+/// button.
+STATIC mp_obj_t pyb_hard_reset(void) {
+ // disable wlan services
+ wlan_servers_stop();
+ wlan_sl_disable();
+ // perform a SoC reset
+ PRCMSOCReset();
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_0(pyb_hard_reset_obj, pyb_hard_reset);
+
+#ifdef DEBUG
+/// \function info([dump_alloc_table])
+/// Print out some run time info which is helpful duirng development.
+STATIC mp_obj_t pyb_info(uint n_args, const mp_obj_t *args) {
+ // FreeRTOS info
+ {
+ printf("---------------------------------------------\n");
+ printf("FreeRTOS\n");
+ printf("---------------------------------------------\n");
+ printf("Total heap: %u\n", configTOTAL_HEAP_SIZE);
+ printf("Free heap: %u\n", xPortGetFreeHeapSize());
+ printf("MpTask min free stack: %u\n", (unsigned int)uxTaskGetStackHighWaterMark((TaskHandle_t)mpTaskHandle));
+ printf("ServersTask min free stack: %u\n", (unsigned int)uxTaskGetStackHighWaterMark((TaskHandle_t)svTaskHandle));
+ printf("SlTask min free stack: %u\n", (unsigned int)uxTaskGetStackHighWaterMark(xSimpleLinkSpawnTaskHndl));
+ printf("IdleTask min free stack: %u\n", (unsigned int)uxTaskGetStackHighWaterMark(xTaskGetIdleTaskHandle()));
+
+ uint32_t *pstack = (uint32_t *)&_stack;
+ while (*pstack == 0x55555555) {
+ pstack++;
+ }
+ printf("MAIN min free stack: %u\n", pstack - ((uint32_t *)&_stack));
+ printf("---------------------------------------------\n");
+ }
+
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_info_obj, 0, 1, pyb_info);
+#endif
+
+/// \function unique_id()
+/// Returns a string of 6 bytes (48 bits), which is the unique MAC address of the SoC
+STATIC mp_obj_t pyb_mac(void) {
+ uint8_t mac[6];
+ wlan_get_mac (mac);
+ return mp_obj_new_bytes(mac, 6);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_0(pyb_mac_obj, pyb_mac);
+
+/// \function freq()
+/// Returns the CPU frequency: (F_CPU).
+STATIC mp_obj_t pyb_freq(void) {
+ return mp_obj_new_int(HAL_FCPU_HZ);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_0(pyb_freq_obj, pyb_freq);
+
+/// \function sync()
+/// Sync all file systems.
+STATIC mp_obj_t pyb_sync(void) {
+ sflash_disk_flush();
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_0(pyb_sync_obj, pyb_sync);
+
+/// \function millis()
+/// Returns the number of milliseconds since the board was last reset.
+///
+/// The result is always a micropython smallint (31-bit signed number), so
+/// after 2^30 milliseconds (about 12.4 days) this will start to return
+/// negative numbers.
+STATIC mp_obj_t pyb_millis(void) {
+ // We want to "cast" the 32 bit unsigned into a small-int. This means
+ // copying the MSB down 1 bit (extending the sign down), which is
+ // equivalent to just using the MP_OBJ_NEW_SMALL_INT macro.
+ return MP_OBJ_NEW_SMALL_INT(HAL_GetTick());
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_0(pyb_millis_obj, pyb_millis);
+
+/// \function elapsed_millis(start)
+/// Returns the number of milliseconds which have elapsed since `start`.
+///
+/// This function takes care of counter wrap, and always returns a positive
+/// number. This means it can be used to measure periods upto about 12.4 days.
+///
+/// Example:
+/// start = pyb.millis()
+/// while pyb.elapsed_millis(start) < 1000:
+/// # Perform some operation
+STATIC mp_obj_t pyb_elapsed_millis(mp_obj_t start) {
+ uint32_t startMillis = mp_obj_get_int(start);
+ uint32_t currMillis = HAL_GetTick();
+ return MP_OBJ_NEW_SMALL_INT((currMillis - startMillis) & 0x3fffffff);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_elapsed_millis_obj, pyb_elapsed_millis);
+
+/// \function micros()
+/// Returns the number of microseconds since the board was last reset.
+///
+/// The result is always a micropython smallint (31-bit signed number), so
+/// after 2^30 microseconds (about 17.8 minutes) this will start to return
+/// negative numbers.
+STATIC mp_obj_t pyb_micros(void) {
+ // We want to "cast" the 32 bit unsigned into a small-int. This means
+ // copying the MSB down 1 bit (extending the sign down), which is
+ // equivalent to just using the MP_OBJ_NEW_SMALL_INT macro.
+ return MP_OBJ_NEW_SMALL_INT(sys_tick_get_microseconds());
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_0(pyb_micros_obj, pyb_micros);
+
+/// \function elapsed_micros(start)
+/// Returns the number of microseconds which have elapsed since `start`.
+///
+/// This function takes care of counter wrap, and always returns a positive
+/// number. This means it can be used to measure periods upto about 17.8 minutes.
+///
+/// Example:
+/// start = pyb.micros()
+/// while pyb.elapsed_micros(start) < 1000:
+/// # Perform some operation
+STATIC mp_obj_t pyb_elapsed_micros(mp_obj_t start) {
+ uint32_t startMicros = mp_obj_get_int(start);
+ uint32_t currMicros = sys_tick_get_microseconds();
+ return MP_OBJ_NEW_SMALL_INT((currMicros - startMicros) & 0x3fffffff);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_elapsed_micros_obj, pyb_elapsed_micros);
+
+/// \function delay(ms)
+/// Delay for the given number of milliseconds.
+STATIC mp_obj_t pyb_delay(mp_obj_t ms_in) {
+ mp_int_t ms = mp_obj_get_int(ms_in);
+ if (ms > 0) {
+ HAL_Delay(ms);
+ }
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_delay_obj, pyb_delay);
+
+/// \function udelay(us)
+/// Delay for the given number of microseconds.
+STATIC mp_obj_t pyb_udelay(mp_obj_t usec_in) {
+ mp_int_t usec = mp_obj_get_int(usec_in);
+ if (usec > 0) {
+ uint32_t count = 0;
+ const uint32_t utime = ((HAL_FCPU_HZ / 1000000) * (usec / 4));
+ while (++count <= utime) {
+ }
+ }
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_udelay_obj, pyb_udelay);
+
+STATIC mp_obj_t pyb_stop(void) {
+ return mp_const_none;
+}
+
+MP_DEFINE_CONST_FUN_OBJ_0(pyb_stop_obj, pyb_stop);
+
+STATIC mp_obj_t pyb_standby(void) {
+ return mp_const_none;
+}
+
+MP_DEFINE_CONST_FUN_OBJ_0(pyb_standby_obj, pyb_standby);
+
+/// \function repl_uart(uart)
+/// Get or set the UART object that the REPL is repeated on.
+STATIC mp_obj_t pyb_repl_uart(uint n_args, const mp_obj_t *args) {
+ if (n_args == 0) {
+ if (MP_STATE_PORT(pyb_stdio_uart) == NULL) {
+ return mp_const_none;
+ } else {
+ return MP_STATE_PORT(pyb_stdio_uart);
+ }
+ } else {
+ if (args[0] == mp_const_none) {
+ MP_STATE_PORT(pyb_stdio_uart) = NULL;
+ } else if (mp_obj_get_type(args[0]) == &pyb_uart_type) {
+ MP_STATE_PORT(pyb_stdio_uart) = args[0];
+ } else {
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_num_type_invalid_arguments));
+ }
+ return mp_const_none;
+ }
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_repl_uart_obj, 0, 1, pyb_repl_uart);
+
+MP_DECLARE_CONST_FUN_OBJ(pyb_main_obj); // defined in main.c
+
+STATIC const mp_map_elem_t pyb_module_globals_table[] = {
+ { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_pyb) },
+
+ { MP_OBJ_NEW_QSTR(MP_QSTR_hard_reset), (mp_obj_t)&pyb_hard_reset_obj },
+#ifdef DEBUG
+ { MP_OBJ_NEW_QSTR(MP_QSTR_info), (mp_obj_t)&pyb_info_obj },
+#endif
+ { MP_OBJ_NEW_QSTR(MP_QSTR_mac), (mp_obj_t)&pyb_mac_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_freq), (mp_obj_t)&pyb_freq_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_repl_info), (mp_obj_t)&pyb_set_repl_info_obj },
+
+ { MP_OBJ_NEW_QSTR(MP_QSTR_wfi), (mp_obj_t)&pyb_wfi_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_disable_irq), (mp_obj_t)&pyb_disable_irq_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_enable_irq), (mp_obj_t)&pyb_enable_irq_obj },
+
+ { MP_OBJ_NEW_QSTR(MP_QSTR_stop), (mp_obj_t)&pyb_stop_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_standby), (mp_obj_t)&pyb_standby_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_main), (mp_obj_t)&pyb_main_obj },
+
+ { MP_OBJ_NEW_QSTR(MP_QSTR_repl_uart), (mp_obj_t)&pyb_repl_uart_obj },
+
+ { MP_OBJ_NEW_QSTR(MP_QSTR_millis), (mp_obj_t)&pyb_millis_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_elapsed_millis), (mp_obj_t)&pyb_elapsed_millis_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_micros), (mp_obj_t)&pyb_micros_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_elapsed_micros), (mp_obj_t)&pyb_elapsed_micros_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_delay), (mp_obj_t)&pyb_delay_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_udelay), (mp_obj_t)&pyb_udelay_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_sync), (mp_obj_t)&pyb_sync_obj },
+
+ //{ MP_OBJ_NEW_QSTR(MP_QSTR_Timer), (mp_obj_t)&pyb_timer_type },
+
+#if MICROPY_HW_ENABLE_RNG
+ { MP_OBJ_NEW_QSTR(MP_QSTR_rng), (mp_obj_t)&pyb_rng_get_obj },
+#endif
+
+#if MICROPY_HW_ENABLE_RTC
+ { MP_OBJ_NEW_QSTR(MP_QSTR_RTC), (mp_obj_t)&pyb_rtc_type },
+#endif
+
+ { MP_OBJ_NEW_QSTR(MP_QSTR_GPIO), (mp_obj_t)&gpio_type },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_ExtInt), (mp_obj_t)&extint_type },
+
+ { MP_OBJ_NEW_QSTR(MP_QSTR_UART), (mp_obj_t)&pyb_uart_type },
+};
+
+STATIC MP_DEFINE_CONST_DICT(pyb_module_globals, pyb_module_globals_table);
+
+const mp_obj_module_t pyb_module = {
+ .base = { &mp_type_module },
+ .name = MP_QSTR_pyb,
+ .globals = (mp_obj_dict_t*)&pyb_module_globals,
+};
diff --git a/cc3200/mods/moduos.c b/cc3200/mods/moduos.c
new file mode 100644
index 000000000..9058a4817
--- /dev/null
+++ b/cc3200/mods/moduos.c
@@ -0,0 +1,337 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2013, 2014 Damien P. George
+ * Copyright (c) 2015 Daniel Campora
+ *
+ * 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 <string.h>
+#include "std.h"
+
+#include "mpconfig.h"
+#include "nlr.h"
+#include "misc.h"
+#include "qstr.h"
+#include "obj.h"
+#include "objtuple.h"
+#include "ff.h"
+#include "diskio.h"
+#include "sflash_diskio.h"
+#include "file.h"
+#include "modutime.h"
+#include "random.h"
+#include "sd_diskio.h"
+
+/// \module os - basic "operating system" services
+///
+/// The `os` module contains functions for filesystem access and `urandom`.
+///
+/// The filesystem has `/` as the root directory, and the available physical
+/// drives are accessible from here. They are currently:
+///
+/// /SFLASH -- the serial flash filesystem
+/// /SD -- the SD card (if it exists)
+///
+/// On boot up, the current directory is `/SFLASH` if no SD card is inserted,
+/// otherwise it is `/SD`.
+
+STATIC bool sd_in_root(void) {
+#if MICROPY_HW_HAS_SDCARD
+ return sd_disk_ready();
+#else
+ return false;
+#endif
+}
+
+/// \function chdir(path)
+/// Change current directory.
+STATIC mp_obj_t os_chdir(mp_obj_t path_in) {
+ const char *path;
+ path = mp_obj_str_get_str(path_in);
+
+ FRESULT res = f_chdrive(path);
+
+ if (res == FR_OK) {
+ res = f_chdir(path);
+ }
+ // TODO: Warn if too many open files...
+ if (res != FR_OK) {
+ // TODO should be mp_type_FileNotFoundError
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "No such file or directory: '%s'", path));
+ }
+
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(os_chdir_obj, os_chdir);
+
+/// \function getcwd()
+/// Get the current directory.
+STATIC mp_obj_t os_getcwd(void) {
+ char buf[MICROPY_ALLOC_PATH_MAX + 1];
+ FRESULT res = f_getcwd(buf, sizeof buf);
+
+ if (res != FR_OK) {
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(fresult_to_errno_table[res])));
+ }
+
+ return mp_obj_new_str(buf, strlen(buf), false);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_0(os_getcwd_obj, os_getcwd);
+
+/// \function listdir([dir])
+/// With no argument, list the current directory. Otherwise list the given directory.
+STATIC mp_obj_t os_listdir(mp_uint_t n_args, const mp_obj_t *args) {
+ bool is_str_type = true;
+ const char *path;
+ if (n_args == 1) {
+ if (mp_obj_get_type(args[0]) == &mp_type_bytes) {
+ is_str_type = false;
+ }
+ path = mp_obj_str_get_str(args[0]);
+ } else {
+ path = "";
+ }
+
+ // "hack" to list root directory
+ if (path[0] == '/' && path[1] == '\0') {
+ mp_obj_t dir_list = mp_obj_new_list(0, NULL);
+ mp_obj_list_append(dir_list, MP_OBJ_NEW_QSTR(MP_QSTR_SFLASH));
+ if (sd_in_root()) {
+ mp_obj_list_append(dir_list, MP_OBJ_NEW_QSTR(MP_QSTR_SD));
+ }
+ return dir_list;
+ }
+
+ FRESULT res;
+ FILINFO fno;
+ DIR dir;
+
+ res = f_opendir(&dir, path); /* Open the directory */
+ if (res != FR_OK) {
+ // TODO should be mp_type_FileNotFoundError
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "No such file or directory: '%s'", path));
+ }
+
+ mp_obj_t dir_list = mp_obj_new_list(0, NULL);
+
+ for (;;) {
+ res = f_readdir(&dir, &fno); /* Read a directory item */
+ if (res != FR_OK || fno.fname[0] == 0) break; /* Break on error or end of dir */
+ if (fno.fname[0] == '.' && fno.fname[1] == 0) continue; /* Ignore . entry */
+ if (fno.fname[0] == '.' && fno.fname[1] == '.' && fno.fname[2] == 0) continue; /* Ignore .. entry */
+
+ char *fn = fno.fname;
+
+ // make a string object for this entry
+ mp_obj_t entry_o;
+ if (is_str_type) {
+ entry_o = mp_obj_new_str(fn, strlen(fn), false);
+ } else {
+ entry_o = mp_obj_new_bytes((const byte*)fn, strlen(fn));
+ }
+
+ // add the entry to the list
+ mp_obj_list_append(dir_list, entry_o);
+ }
+
+ f_closedir(&dir);
+
+ return dir_list;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(os_listdir_obj, 0, 1, os_listdir);
+
+/// \function mkdir(path)
+/// Create a new directory.
+STATIC mp_obj_t os_mkdir(mp_obj_t path_o) {
+ const char *path = mp_obj_str_get_str(path_o);
+ FRESULT res = f_mkdir(path);
+ switch (res) {
+ case FR_OK:
+ return mp_const_none;
+ case FR_EXIST:
+ // TODO should be FileExistsError
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "File exists: '%s'", path));
+ default:
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "Error creating directory '%s'", path));
+ }
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(os_mkdir_obj, os_mkdir);
+
+/// \function remove(path)
+/// Remove a file.
+STATIC mp_obj_t os_remove(mp_obj_t path_o) {
+ const char *path = mp_obj_str_get_str(path_o);
+ // TODO check that path is actually a file before trying to unlink it
+ FRESULT res = f_unlink(path);
+ switch (res) {
+ case FR_OK:
+ return mp_const_none;
+ default:
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "Error removing file '%s'", path));
+ }
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(os_remove_obj, os_remove);
+
+/// \function rmdir(path)
+/// Remove a directory.
+STATIC mp_obj_t os_rmdir(mp_obj_t path_o) {
+ const char *path = mp_obj_str_get_str(path_o);
+ // TODO check that path is actually a directory before trying to unlink it
+ FRESULT res = f_unlink(path);
+ switch (res) {
+ case FR_OK:
+ return mp_const_none;
+ default:
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "Error removing directory '%s'", path));
+ }
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(os_rmdir_obj, os_rmdir);
+
+// Checks for path equality, ignoring trailing slashes:
+// path_equal(/, /) -> true
+// path_equal(/flash//, /flash) -> true
+// second argument must be in canonical form (meaning no trailing slash, unless it's just /)
+STATIC bool path_equal(const char *path, const char *path_canonical) {
+ for (; *path_canonical != '\0' && *path == *path_canonical; ++path, ++path_canonical) {
+ }
+ if (*path_canonical != '\0') {
+ return false;
+ }
+ for (; *path == '/'; ++path) {
+ }
+ return *path == '\0';
+}
+
+/// \function stat(path)
+/// Get the status of a file or directory.
+STATIC mp_obj_t os_stat(mp_obj_t path_in) {
+ const char *path = mp_obj_str_get_str(path_in);
+ stoupper((char *)path);
+
+ FILINFO fno;
+ FRESULT res;
+ if (path_equal(path, "/") || path_equal(path, "/SFLASH") || path_equal(path, "/SD")) {
+ // stat built-in directory
+ if (path[1] == 'S' && !sd_in_root()) {
+ // no /SD directory
+ res = FR_NO_PATH;
+ goto error;
+ }
+ fno.fsize = 0;
+ fno.fdate = 0;
+ fno.ftime = 0;
+ fno.fattrib = AM_DIR;
+ } else {
+ res = f_stat(path, &fno);
+ if (res != FR_OK) {
+ goto error;
+ }
+ }
+
+ mp_obj_tuple_t *t = mp_obj_new_tuple(10, NULL);
+ mp_int_t mode = 0;
+ if (fno.fattrib & AM_DIR) {
+ mode |= 0x4000; // stat.S_IFDIR
+ } else {
+ mode |= 0x8000; // stat.S_IFREG
+ }
+ mp_int_t seconds = mod_time_seconds_since_2000(
+ 1980 + ((fno.fdate >> 9) & 0x7f),
+ (fno.fdate >> 5) & 0x0f,
+ fno.fdate & 0x1f,
+ (fno.ftime >> 11) & 0x1f,
+ (fno.ftime >> 5) & 0x3f,
+ 2 * (fno.ftime & 0x1f)
+ );
+ t->items[0] = mp_obj_new_int(mode); // st_mode
+ t->items[1] = MP_OBJ_NEW_SMALL_INT(0); // st_ino
+ t->items[2] = MP_OBJ_NEW_SMALL_INT(0); // st_dev
+ t->items[3] = MP_OBJ_NEW_SMALL_INT(0); // st_nlink
+ t->items[4] = MP_OBJ_NEW_SMALL_INT(0); // st_uid
+ t->items[5] = MP_OBJ_NEW_SMALL_INT(0); // st_gid
+ t->items[6] = mp_obj_new_int(fno.fsize); // st_size
+ t->items[7] = mp_obj_new_int(seconds); // st_atime
+ t->items[8] = t->items[7]; // st_mtime
+ t->items[9] = t->items[7]; // st_ctime
+
+ return t;
+
+error:
+ nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(fresult_to_errno_table[res])));
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(os_stat_obj, os_stat);
+
+/// \function sync()
+/// Sync all filesystems.
+STATIC mp_obj_t os_sync(void) {
+ sflash_disk_flush();
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_0(os_sync_obj, os_sync);
+
+#if MICROPY_HW_ENABLE_RNG
+/// \function urandom(n)
+/// Return a bytes object with n random bytes, generated by the hardware
+/// random number generator.
+STATIC mp_obj_t os_urandom(mp_obj_t num) {
+ mp_int_t n = mp_obj_get_int(num);
+ vstr_t vstr;
+ vstr_init_len(&vstr, n);
+ for (int i = 0; i < n; i++) {
+ vstr.buf[i] = rng_get();
+ }
+ return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(os_urandom_obj, os_urandom);
+#endif
+
+STATIC const mp_map_elem_t os_module_globals_table[] = {
+ { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_uos) },
+
+ { MP_OBJ_NEW_QSTR(MP_QSTR_chdir), (mp_obj_t)&os_chdir_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_getcwd), (mp_obj_t)&os_getcwd_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_listdir), (mp_obj_t)&os_listdir_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_mkdir), (mp_obj_t)&os_mkdir_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_remove), (mp_obj_t)&os_remove_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_rmdir), (mp_obj_t)&os_rmdir_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_stat), (mp_obj_t)&os_stat_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_unlink), (mp_obj_t)&os_remove_obj }, // unlink aliases to remove
+
+ { MP_OBJ_NEW_QSTR(MP_QSTR_sync), (mp_obj_t)&os_sync_obj },
+
+ /// \constant sep - separation character used in paths
+ { MP_OBJ_NEW_QSTR(MP_QSTR_sep), MP_OBJ_NEW_QSTR(MP_QSTR__slash_) },
+
+#if MICROPY_HW_ENABLE_RNG
+ { MP_OBJ_NEW_QSTR(MP_QSTR_urandom), (mp_obj_t)&os_urandom_obj },
+#endif
+};
+
+STATIC MP_DEFINE_CONST_DICT(os_module_globals, os_module_globals_table);
+
+const mp_obj_module_t mp_module_uos = {
+ .base = { &mp_type_module },
+ .name = MP_QSTR_uos,
+ .globals = (mp_obj_dict_t*)&os_module_globals,
+};
diff --git a/cc3200/mods/modusocket.c b/cc3200/mods/modusocket.c
new file mode 100644
index 000000000..7356942f2
--- /dev/null
+++ b/cc3200/mods/modusocket.c
@@ -0,0 +1,451 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2013, 2014 Damien P. George
+ * Copyright (c) 2015 Daniel Campora
+ *
+ * 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 <std.h>
+#include <stdint.h>
+#include <string.h>
+
+#include "simplelink.h"
+#include "mpconfig.h"
+#include MICROPY_HAL_H
+#include "nlr.h"
+#include "misc.h"
+#include "qstr.h"
+#include "obj.h"
+#include "objtuple.h"
+#include "objlist.h"
+#include "runtime.h"
+#include "modnetwork.h"
+#include "mpexception.h"
+#include "mpstate.h"
+
+/******************************************************************************/
+// socket class
+
+STATIC const mp_obj_type_t socket_type;
+
+// constructor socket(family=AF_INET, type=SOCK_STREAM, proto=IPPROTO_TCP, fileno=None)
+STATIC mp_obj_t socket_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
+ mp_arg_check_num(n_args, n_kw, 0, 4, false);
+
+ // create socket object (not bound to any NIC yet)
+ mod_network_socket_obj_t *s = m_new_obj_with_finaliser(mod_network_socket_obj_t);
+ s->base.type = (mp_obj_t)&socket_type;
+ s->nic = MP_OBJ_NULL;
+ s->nic_type = NULL;
+ s->u_param.domain = AF_INET;
+ s->u_param.type = SOCK_STREAM;
+ s->u_param.proto = IPPROTO_TCP;
+ s->u_param.fileno = -1;
+ if (n_args >= 1) {
+ s->u_param.domain = mp_obj_get_int(args[0]);
+ if (n_args >= 2) {
+ s->u_param.type = mp_obj_get_int(args[1]);
+ if (n_args >= 3) {
+ s->u_param.proto = mp_obj_get_int(args[2]);
+ if (n_args == 4) {
+ s->u_param.fileno = mp_obj_get_int(args[3]);
+ }
+ }
+ }
+ }
+ return s;
+}
+
+STATIC void socket_select_nic(mod_network_socket_obj_t *self, const byte *ip) {
+ if (self->nic == MP_OBJ_NULL) {
+ // select NIC based on IP
+ self->nic = mod_network_find_nic(ip);
+ self->nic_type = (mod_network_nic_type_t*)mp_obj_get_type(self->nic);
+
+ // call the NIC to open the socket
+ int _errno;
+ if (self->nic_type->socket(self, &_errno) != 0) {
+ nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(_errno)));
+ }
+ }
+}
+// method socket.close()
+STATIC mp_obj_t socket_close(mp_obj_t self_in) {
+ mod_network_socket_obj_t *self = self_in;
+ if (self->nic != MP_OBJ_NULL) {
+ self->nic_type->close(self);
+ }
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(socket_close_obj, socket_close);
+
+// method socket.bind(address)
+STATIC mp_obj_t socket_bind(mp_obj_t self_in, mp_obj_t addr_in) {
+ mod_network_socket_obj_t *self = self_in;
+
+ // get address
+ uint8_t ip[MOD_NETWORK_IPV4ADDR_BUF_SIZE];
+ mp_uint_t port = mod_network_parse_inet_addr(addr_in, ip);
+
+ // check if we need to select a NIC
+ socket_select_nic(self, ip);
+
+ // call the NIC to bind the socket
+ int _errno;
+ if (self->nic_type->bind(self, ip, port, &_errno) != 0) {
+ nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(_errno)));
+ }
+
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_bind_obj, socket_bind);
+
+// method socket.listen(backlog)
+STATIC mp_obj_t socket_listen(mp_obj_t self_in, mp_obj_t backlog) {
+ mod_network_socket_obj_t *self = self_in;
+
+ if (self->nic == MP_OBJ_NULL) {
+ // not connected
+ nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(ENOTCONN)));
+ }
+
+ int _errno;
+ if (self->nic_type->listen(self, mp_obj_get_int(backlog), &_errno) != 0) {
+ nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(_errno)));
+ }
+
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_listen_obj, socket_listen);
+
+// method socket.accept()
+STATIC mp_obj_t socket_accept(mp_obj_t self_in) {
+ mod_network_socket_obj_t *self = self_in;
+
+ // create new socket object
+ // starts with empty NIC so that finaliser doesn't run close() method if accept() fails
+ mod_network_socket_obj_t *socket2 = m_new_obj_with_finaliser(mod_network_socket_obj_t);
+ socket2->base.type = (mp_obj_t)&socket_type;
+ socket2->nic = MP_OBJ_NULL;
+ socket2->nic_type = NULL;
+
+ // accept incoming connection
+ uint8_t ip[MOD_NETWORK_IPV4ADDR_BUF_SIZE];
+ mp_uint_t port;
+ int _errno;
+ if (self->nic_type->accept(self, socket2, ip, &port, &_errno) != 0) {
+ nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(_errno)));
+ }
+
+ // new socket has valid state, so set the NIC to the same as parent
+ socket2->nic = self->nic;
+ socket2->nic_type = self->nic_type;
+
+ // make the return value
+ mp_obj_tuple_t *client = mp_obj_new_tuple(2, NULL);
+ client->items[0] = socket2;
+ client->items[1] = mod_network_format_inet_addr(ip, port);
+
+ return client;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(socket_accept_obj, socket_accept);
+
+// method socket.connect(address)
+STATIC mp_obj_t socket_connect(mp_obj_t self_in, mp_obj_t addr_in) {
+ mod_network_socket_obj_t *self = self_in;
+
+ // get address
+ uint8_t ip[MOD_NETWORK_IPV4ADDR_BUF_SIZE];
+ mp_uint_t port = mod_network_parse_inet_addr(addr_in, ip);
+
+ // check if we need to select a NIC
+ socket_select_nic(self, ip);
+
+ // call the NIC to connect the socket
+ int _errno;
+ if (self->nic_type->connect(self, ip, port, &_errno) != 0) {
+ nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(_errno)));
+ }
+
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_connect_obj, socket_connect);
+
+// method socket.send(bytes)
+STATIC mp_obj_t socket_send(mp_obj_t self_in, mp_obj_t buf_in) {
+ mod_network_socket_obj_t *self = self_in;
+ if (self->nic == MP_OBJ_NULL) {
+ // not connected
+ nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(EBADF)));
+ }
+ mp_buffer_info_t bufinfo;
+ mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_READ);
+ int _errno;
+ mp_uint_t ret = self->nic_type->send(self, bufinfo.buf, bufinfo.len, &_errno);
+ if (ret == -1) {
+ nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(_errno)));
+ }
+ return mp_obj_new_int_from_uint(ret);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_send_obj, socket_send);
+
+// method socket.recv(bufsize)
+STATIC mp_obj_t socket_recv(mp_obj_t self_in, mp_obj_t len_in) {
+ mod_network_socket_obj_t *self = self_in;
+ if (self->nic == MP_OBJ_NULL) {
+ // not connected
+ nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(ENOTCONN)));
+ }
+ mp_int_t len = mp_obj_get_int(len_in);
+ vstr_t vstr;
+ vstr_init_len(&vstr, len);
+ int _errno;
+ mp_uint_t ret = self->nic_type->recv(self, (byte*)vstr.buf, len, &_errno);
+ if (ret == -1) {
+ nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(_errno)));
+ }
+ if (ret == 0) {
+ return mp_const_empty_bytes;
+ }
+ vstr.len = ret;
+ vstr.buf[vstr.len] = '\0';
+ return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_recv_obj, socket_recv);
+
+// method socket.sendto(bytes, address)
+STATIC mp_obj_t socket_sendto(mp_obj_t self_in, mp_obj_t data_in, mp_obj_t addr_in) {
+ mod_network_socket_obj_t *self = self_in;
+
+ // get the data
+ mp_buffer_info_t bufinfo;
+ mp_get_buffer_raise(data_in, &bufinfo, MP_BUFFER_READ);
+
+ // get address
+ uint8_t ip[MOD_NETWORK_IPV4ADDR_BUF_SIZE];
+ mp_uint_t port = mod_network_parse_inet_addr(addr_in, ip);
+
+ // check if we need to select a NIC
+ socket_select_nic(self, ip);
+
+ // call the NIC to sendto
+ int _errno;
+ mp_int_t ret = self->nic_type->sendto(self, bufinfo.buf, bufinfo.len, ip, port, &_errno);
+ if (ret == -1) {
+ nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(_errno)));
+ }
+
+ return mp_obj_new_int(ret);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_3(socket_sendto_obj, socket_sendto);
+
+// method socket.recvfrom(bufsize)
+STATIC mp_obj_t socket_recvfrom(mp_obj_t self_in, mp_obj_t len_in) {
+ mod_network_socket_obj_t *self = self_in;
+ if (self->nic == MP_OBJ_NULL) {
+ // not connected
+ nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(ENOTCONN)));
+ }
+ vstr_t vstr;
+ vstr_init_len(&vstr, mp_obj_get_int(len_in));
+ byte ip[4];
+ mp_uint_t port;
+ int _errno;
+ mp_int_t ret = self->nic_type->recvfrom(self, (byte*)vstr.buf, vstr.len, ip, &port, &_errno);
+ if (ret == -1) {
+ nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(_errno)));
+ }
+ mp_obj_t tuple[2];
+ if (ret == 0) {
+ tuple[0] = mp_const_empty_bytes;
+ } else {
+ vstr.len = ret;
+ vstr.buf[vstr.len] = '\0';
+ tuple[0] = mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
+ }
+ tuple[1] = mod_network_format_inet_addr(ip, port);
+ return mp_obj_new_tuple(2, tuple);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_recvfrom_obj, socket_recvfrom);
+
+// method socket.setsockopt(level, optname, value)
+STATIC mp_obj_t socket_setsockopt(mp_uint_t n_args, const mp_obj_t *args) {
+ mod_network_socket_obj_t *self = args[0];
+
+ mp_int_t level = mp_obj_get_int(args[1]);
+ mp_int_t opt = mp_obj_get_int(args[2]);
+
+ const void *optval;
+ mp_uint_t optlen;
+ mp_int_t val;
+ if (mp_obj_is_integer(args[3])) {
+ val = mp_obj_int_get_truncated(args[3]);
+ optval = &val;
+ optlen = sizeof(val);
+ } else {
+ mp_buffer_info_t bufinfo;
+ mp_get_buffer_raise(args[3], &bufinfo, MP_BUFFER_READ);
+ optval = bufinfo.buf;
+ optlen = bufinfo.len;
+ }
+
+ int _errno;
+ if (self->nic_type->setsockopt(self, level, opt, optval, optlen, &_errno) != 0) {
+ nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(_errno)));
+ }
+
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(socket_setsockopt_obj, 4, 4, socket_setsockopt);
+
+// method socket.settimeout(value)
+// timeout=0 means non-blocking
+// timeout=None means blocking
+// otherwise, timeout is in seconds
+STATIC mp_obj_t socket_settimeout(mp_obj_t self_in, mp_obj_t timeout_in) {
+ mod_network_socket_obj_t *self = self_in;
+ if (self->nic == MP_OBJ_NULL) {
+ // not connected
+ nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(ENOTCONN)));
+ }
+ mp_uint_t timeout;
+ if (timeout_in == mp_const_none) {
+ timeout = -1;
+ } else {
+ timeout = 1000 * mp_obj_get_int(timeout_in);
+ }
+ int _errno;
+ if (self->nic_type->settimeout(self, timeout, &_errno) != 0) {
+ nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(_errno)));
+ }
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_settimeout_obj, socket_settimeout);
+
+// method socket.setblocking(flag)
+STATIC mp_obj_t socket_setblocking(mp_obj_t self_in, mp_obj_t blocking) {
+ if (mp_obj_is_true(blocking)) {
+ return socket_settimeout(self_in, mp_const_none);
+ } else {
+ return socket_settimeout(self_in, MP_OBJ_NEW_SMALL_INT(0));
+ }
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_setblocking_obj, socket_setblocking);
+
+STATIC const mp_map_elem_t socket_locals_dict_table[] = {
+ { MP_OBJ_NEW_QSTR(MP_QSTR___del__), (mp_obj_t)&socket_close_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_close), (mp_obj_t)&socket_close_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_bind), (mp_obj_t)&socket_bind_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_listen), (mp_obj_t)&socket_listen_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_accept), (mp_obj_t)&socket_accept_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_connect), (mp_obj_t)&socket_connect_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_send), (mp_obj_t)&socket_send_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_recv), (mp_obj_t)&socket_recv_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_sendto), (mp_obj_t)&socket_sendto_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_recvfrom), (mp_obj_t)&socket_recvfrom_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_setsockopt), (mp_obj_t)&socket_setsockopt_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_settimeout), (mp_obj_t)&socket_settimeout_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_setblocking), (mp_obj_t)&socket_setblocking_obj },
+};
+
+STATIC MP_DEFINE_CONST_DICT(socket_locals_dict, socket_locals_dict_table);
+
+mp_uint_t socket_ioctl(mp_obj_t self_in, mp_uint_t request, mp_uint_t arg, int *errcode) {
+ mod_network_socket_obj_t *self = self_in;
+ return self->nic_type->ioctl(self, request, arg, errcode);
+}
+
+STATIC const mp_stream_p_t socket_stream_p = {
+ .ioctl = socket_ioctl,
+ .is_text = false,
+};
+
+STATIC const mp_obj_type_t socket_type = {
+ { &mp_type_type },
+ .name = MP_QSTR_socket,
+ .make_new = socket_make_new,
+ .stream_p = &socket_stream_p,
+ .locals_dict = (mp_obj_t)&socket_locals_dict,
+};
+
+/******************************************************************************/
+// usocket module
+
+// function usocket.getaddrinfo(host, port)
+/// \function getaddrinfo(host, port)
+STATIC mp_obj_t mod_usocket_getaddrinfo(mp_obj_t host_in, mp_obj_t port_in) {
+ mp_uint_t hlen;
+ const char *host = mp_obj_str_get_data(host_in, &hlen);
+ mp_int_t port = mp_obj_get_int(port_in);
+
+ // find a NIC that can do a name lookup
+ 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];
+ mod_network_nic_type_t *nic_type = (mod_network_nic_type_t*)mp_obj_get_type(nic);
+ if (nic_type->gethostbyname != NULL) {
+ // Only IPv4 is supported
+ uint8_t out_ip[MOD_NETWORK_IPV4ADDR_BUF_SIZE];
+ int32_t result = nic_type->gethostbyname(nic, host, hlen, out_ip, AF_INET);
+ if (result != 0) {
+ nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(result)));
+ }
+ mp_obj_tuple_t *tuple = mp_obj_new_tuple(5, NULL);
+ tuple->items[0] = MP_OBJ_NEW_SMALL_INT(AF_INET);
+ tuple->items[1] = MP_OBJ_NEW_SMALL_INT(SOCK_STREAM);
+ tuple->items[2] = MP_OBJ_NEW_SMALL_INT(0);
+ tuple->items[3] = MP_OBJ_NEW_QSTR(MP_QSTR_);
+ tuple->items[4] = mod_network_format_inet_addr(out_ip, port);
+ return mp_obj_new_list(1, (mp_obj_t*)&tuple);
+ }
+ }
+
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable));
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_usocket_getaddrinfo_obj, mod_usocket_getaddrinfo);
+
+STATIC const mp_map_elem_t mp_module_usocket_globals_table[] = {
+ { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_usocket) },
+
+ { MP_OBJ_NEW_QSTR(MP_QSTR_socket), (mp_obj_t)&socket_type },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_getaddrinfo), (mp_obj_t)&mod_usocket_getaddrinfo_obj },
+
+ // class constants
+ { MP_OBJ_NEW_QSTR(MP_QSTR_AF_INET), MP_OBJ_NEW_SMALL_INT(AF_INET) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_AF_INET6), MP_OBJ_NEW_SMALL_INT(AF_INET6) },
+
+ { MP_OBJ_NEW_QSTR(MP_QSTR_SOCK_STREAM), MP_OBJ_NEW_SMALL_INT(SOCK_STREAM) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_SOCK_DGRAM), MP_OBJ_NEW_SMALL_INT(SOCK_DGRAM) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_SOCK_RAW), MP_OBJ_NEW_SMALL_INT(SOCK_RAW) },
+
+ { MP_OBJ_NEW_QSTR(MP_QSTR_IPPROTO_TCP), MP_OBJ_NEW_SMALL_INT(IPPROTO_TCP) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_IPPROTO_UDP), MP_OBJ_NEW_SMALL_INT(IPPROTO_UDP) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_IPPROTO_RAW), MP_OBJ_NEW_SMALL_INT(IPPROTO_RAW) },
+};
+
+STATIC MP_DEFINE_CONST_DICT(mp_module_usocket_globals, mp_module_usocket_globals_table);
+
+const mp_obj_module_t mp_module_usocket = {
+ .base = { &mp_type_module },
+ .name = MP_QSTR_usocket,
+ .globals = (mp_obj_dict_t*)&mp_module_usocket_globals,
+};
diff --git a/cc3200/mods/modutime.c b/cc3200/mods/modutime.c
new file mode 100644
index 000000000..9dae880e6
--- /dev/null
+++ b/cc3200/mods/modutime.c
@@ -0,0 +1,333 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2013, 2014 Damien P. George
+ * Copyright (c) 2015 Daniel Campora
+ *
+ * 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 "mpconfig.h"
+#include MICROPY_HAL_H
+#include "nlr.h"
+#include "misc.h"
+#include "qstr.h"
+#include "obj.h"
+#include "modutime.h"
+#include "inc/hw_types.h"
+#include "inc/hw_ints.h"
+#include "inc/hw_memmap.h"
+#include "rom_map.h"
+#include "prcm.h"
+#include "pybrtc.h"
+#include "mpexception.h"
+
+
+// LEAPOCH corresponds to 2000-03-01, which is a mod-400 year, immediately
+// after Feb 29. We calculate seconds as a signed integer relative to that.
+//
+// Our timebase is relative to 2000-01-01.
+
+#define LEAPOCH ((31 + 29) * 86400)
+
+#define DAYS_PER_400Y (365*400 + 97)
+#define DAYS_PER_100Y (365*100 + 24)
+#define DAYS_PER_4Y (365*4 + 1)
+
+
+/// \module time - time related functions
+///
+/// The `time` module provides functions for getting the current time and date,
+/// and for sleeping.
+
+STATIC const uint16_t days_since_jan1[]= { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 };
+
+STATIC bool is_leap_year(mp_uint_t year) {
+ return (year % 4 == 0 && year % 100 != 0) || year % 400 == 0;
+}
+
+// Month is one based
+STATIC mp_uint_t mod_time_days_in_month(mp_uint_t year, mp_uint_t month) {
+ mp_uint_t mdays = days_since_jan1[month] - days_since_jan1[month - 1];
+ if (month == 2 && is_leap_year(year)) {
+ mdays++;
+ }
+ return mdays;
+}
+
+// compute the day of the year, between 1 and 366
+// month should be between 1 and 12, date should start at 1
+STATIC mp_uint_t mod_time_year_day(mp_uint_t year, mp_uint_t month, mp_uint_t date) {
+ mp_uint_t yday = days_since_jan1[month - 1] + date;
+ if (month >= 3 && is_leap_year(year)) {
+ yday += 1;
+ }
+ return yday;
+}
+
+// returns the number of seconds, as an integer, since 2000-01-01
+mp_uint_t mod_time_seconds_since_2000(mp_uint_t year, mp_uint_t month, mp_uint_t date, mp_uint_t hour, mp_uint_t minute, mp_uint_t second) {
+ return
+ second
+ + minute * 60
+ + hour * 3600
+ + (mod_time_year_day(year, month, date) - 1
+ + ((year - 2000 + 3) / 4) // add a day each 4 years starting with 2001
+ - ((year - 2000 + 99) / 100) // subtract a day each 100 years starting with 2001
+ + ((year - 2000 + 399) / 400) // add a day each 400 years starting with 2001
+ ) * 86400
+ + (year - 2000) * 31536000;
+}
+
+void mod_time_seconds_since_2000_to_struct_time(mp_uint_t t, mod_struct_time *tm) {
+ // The following algorithm was adapted from musl's __secs_to_tm and adapted
+ // for differences in Micro Python's timebase.
+
+ mp_int_t seconds = t - LEAPOCH;
+
+ mp_int_t days = seconds / 86400;
+ seconds %= 86400;
+ tm->tm_hour = seconds / 3600;
+ tm->tm_min = seconds / 60 % 60;
+ tm->tm_sec = seconds % 60;
+
+ mp_int_t wday = (days + 2) % 7; // Mar 1, 2000 was a Wednesday (2)
+ if (wday < 0) {
+ wday += 7;
+ }
+ tm->tm_wday = wday;
+
+ mp_int_t qc_cycles = days / DAYS_PER_400Y;
+ days %= DAYS_PER_400Y;
+ if (days < 0) {
+ days += DAYS_PER_400Y;
+ qc_cycles--;
+ }
+ mp_int_t c_cycles = days / DAYS_PER_100Y;
+ if (c_cycles == 4) {
+ c_cycles--;
+ }
+ days -= (c_cycles * DAYS_PER_100Y);
+
+ mp_int_t q_cycles = days / DAYS_PER_4Y;
+ if (q_cycles == 25) {
+ q_cycles--;
+ }
+ days -= q_cycles * DAYS_PER_4Y;
+
+ mp_int_t years = days / 365;
+ if (years == 4) {
+ years--;
+ }
+ days -= (years * 365);
+
+ tm->tm_year = 2000 + years + 4 * q_cycles + 100 * c_cycles + 400 * qc_cycles;
+
+ // Note: days_in_month[0] corresponds to March
+ STATIC const int8_t days_in_month[] = {31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 31, 29};
+
+ mp_int_t month;
+ for (month = 0; days_in_month[month] <= days; month++) {
+ days -= days_in_month[month];
+ }
+
+ tm->tm_mon = month + 2;
+ if (tm->tm_mon >= 12) {
+ tm->tm_mon -= 12;
+ tm->tm_year++;
+ }
+ tm->tm_mday = days + 1; // Make one based
+ tm->tm_mon++; // Make one based
+
+ tm->tm_yday = mod_time_year_day(tm->tm_year, tm->tm_mon, tm->tm_mday);
+}
+
+/// \function localtime([secs])
+/// Convert a time expressed in seconds since Jan 1, 2000 into an 8-tuple which
+/// contains: (year, month, mday, hour, minute, second, weekday, yearday)
+/// If secs is not provided or None, then the current time from the RTC is used.
+/// year includes the century (for example 2014)
+/// month is 1-12
+/// mday is 1-31
+/// hour is 0-23
+/// minute is 0-59
+/// second is 0-59
+/// weekday is 0-6 for Mon-Sun.
+/// yearday is 1-366
+STATIC mp_obj_t time_localtime(mp_uint_t n_args, const mp_obj_t *args) {
+ if (n_args == 0 || args[0] == mp_const_none) {
+ mod_struct_time tm;
+ uint32_t seconds;
+ uint16_t mseconds;
+
+ // get the seconds and the milliseconds from the RTC
+ MAP_PRCMRTCGet(&seconds, &mseconds);
+ mseconds = RTC_CYCLES_U16MS(mseconds);
+ mod_time_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(mseconds)
+ };
+ return mp_obj_new_tuple(8, tuple);
+ } else {
+ mp_int_t seconds = mp_obj_get_int(args[0]);
+ mod_struct_time tm;
+ mod_time_seconds_since_2000_to_struct_time(seconds, &tm);
+ mp_obj_t tuple[8] = {
+ tuple[0] = mp_obj_new_int(tm.tm_year),
+ tuple[1] = mp_obj_new_int(tm.tm_mon),
+ tuple[2] = mp_obj_new_int(tm.tm_mday),
+ tuple[3] = mp_obj_new_int(tm.tm_hour),
+ tuple[4] = mp_obj_new_int(tm.tm_min),
+ tuple[5] = mp_obj_new_int(tm.tm_sec),
+ tuple[6] = mp_obj_new_int(tm.tm_wday),
+ tuple[7] = mp_obj_new_int(tm.tm_yday),
+ };
+ return mp_obj_new_tuple(8, tuple);
+ }
+}
+MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(time_localtime_obj, 0, 1, time_localtime);
+
+
+/// \function mktime()
+/// This is inverse function of localtime. It's argument is a full 8-tuple
+/// which expresses a time as per localtime. It returns an integer which is
+/// the number of seconds since Jan 1, 2000.
+STATIC mp_obj_t time_mktime(mp_obj_t tuple) {
+
+ mp_uint_t len;
+ mp_obj_t *elem;
+
+ mp_obj_get_array(tuple, &len, &elem);
+
+ // localtime generates a tuple of len 8. CPython uses 9, so we accept both.
+ if (len < 8 || len > 9) {
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, mpexception_num_type_invalid_arguments));
+ }
+
+ mp_int_t year = mp_obj_get_int(elem[0]);
+ mp_int_t month = mp_obj_get_int(elem[1]);
+ mp_int_t mday = mp_obj_get_int(elem[2]);
+ mp_int_t hours = mp_obj_get_int(elem[3]);
+ mp_int_t minutes = mp_obj_get_int(elem[4]);
+ mp_int_t seconds = mp_obj_get_int(elem[5]);
+
+ // Normalize the tuple. This allows things like:
+ //
+ // tm_tomorrow = list(time.localtime())
+ // tm_tomorrow[2] += 1 # Adds 1 to mday
+ // tomorrow = time.mktime(tm_tommorrow)
+ //
+ // And not have to worry about all the weird overflows.
+ //
+ // You can subtract dates/times this way as well.
+
+ minutes += seconds / 60;
+ if ((seconds = seconds % 60) < 0) {
+ seconds += 60;
+ minutes--;
+ }
+
+ hours += minutes / 60;
+ if ((minutes = minutes % 60) < 0) {
+ minutes += 60;
+ hours--;
+ }
+
+ mday += hours / 24;
+ if ((hours = hours % 24) < 0) {
+ hours += 24;
+ mday--;
+ }
+
+ month--; // make month zero based
+ year += month / 12;
+ if ((month = month % 12) < 0) {
+ month += 12;
+ year--;
+ }
+ month++; // back to one based
+
+ while (mday < 1) {
+ if (--month == 0) {
+ month = 12;
+ year--;
+ }
+ mday += mod_time_days_in_month(year, month);
+ }
+ while (mday > mod_time_days_in_month(year, month)) {
+ mday -= mod_time_days_in_month(year, month);
+ if (++month == 13) {
+ month = 1;
+ year++;
+ }
+ }
+ return mp_obj_new_int_from_uint(mod_time_seconds_since_2000(year, month, mday, hours, minutes, seconds));
+}
+MP_DEFINE_CONST_FUN_OBJ_1(time_mktime_obj, time_mktime);
+
+
+/// \function sleep(milliseconds)
+/// Sleep for the given number of milliseconds.
+STATIC mp_obj_t time_sleep(mp_obj_t milliseconds_o) {
+ HAL_Delay(mp_obj_get_int(milliseconds_o));
+ return mp_const_none;
+}
+MP_DEFINE_CONST_FUN_OBJ_1(time_sleep_obj, time_sleep);
+
+/// \function time()
+/// Returns the number of seconds, as an integer, since 1/1/2000.
+STATIC mp_obj_t time_time(void) {
+ uint32_t seconds;
+ uint16_t mseconds;
+
+ // get the seconds and the milliseconds from the RTC
+ MAP_PRCMRTCGet(&seconds, &mseconds);
+ return mp_obj_new_int(seconds);
+}
+MP_DEFINE_CONST_FUN_OBJ_0(time_time_obj, time_time);
+
+STATIC const mp_map_elem_t time_module_globals_table[] = {
+ { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_utime) },
+
+ { MP_OBJ_NEW_QSTR(MP_QSTR_localtime), (mp_obj_t)&time_localtime_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_mktime), (mp_obj_t)&time_mktime_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_sleep), (mp_obj_t)&time_sleep_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_time), (mp_obj_t)&time_time_obj },
+};
+
+STATIC MP_DEFINE_CONST_DICT(time_module_globals, time_module_globals_table);
+
+const mp_obj_module_t mp_module_utime = {
+ .base = { &mp_type_module },
+ .name = MP_QSTR_utime,
+ .globals = (mp_obj_dict_t*)&time_module_globals,
+};
diff --git a/cc3200/mods/modutime.h b/cc3200/mods/modutime.h
new file mode 100644
index 000000000..5f1e8ed74
--- /dev/null
+++ b/cc3200/mods/modutime.h
@@ -0,0 +1,43 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2013, 2014 Damien P. George
+ * Copyright (c) 2015 Daniel Campora
+ *
+ * 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.
+ */
+
+typedef struct {
+ uint16_t tm_year; // i.e. 2014
+ uint8_t tm_mon; // 1..12
+ uint8_t tm_mday; // 1..31
+ uint8_t tm_hour; // 0..23
+ uint8_t tm_min; // 0..59
+ uint8_t tm_sec; // 0..59
+ uint8_t tm_wday; // 0..6 0 = Monday
+ uint16_t tm_yday; // 1..366
+} mod_struct_time;
+
+
+extern mp_uint_t mod_time_seconds_since_2000(mp_uint_t year, mp_uint_t month, mp_uint_t date,
+ mp_uint_t hour, mp_uint_t minute, mp_uint_t second);
+
+extern void mod_time_seconds_since_2000_to_struct_time(mp_uint_t t, mod_struct_time *tm);
diff --git a/cc3200/mods/modwlan.c b/cc3200/mods/modwlan.c
new file mode 100644
index 000000000..22b8cae9c
--- /dev/null
+++ b/cc3200/mods/modwlan.c
@@ -0,0 +1,1199 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2015 Daniel Campora
+ *
+ * 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 "std.h"
+#include <stdint.h>
+#include <stdbool.h>
+
+#include "simplelink.h"
+#include "mpconfig.h"
+#include MICROPY_HAL_H
+#include "misc.h"
+#include "nlr.h"
+#include "qstr.h"
+#include "obj.h"
+#include "objtuple.h"
+#include "objlist.h"
+#include "runtime.h"
+#include "modnetwork.h"
+#include "modwlan.h"
+#include "pybioctl.h"
+#include "pybuart.h"
+#include "pybstdio.h"
+#include "osi.h"
+#include "debug.h"
+#include "serverstask.h"
+#include "mpexception.h"
+
+#ifdef USE_FREERTOS
+#include "FreeRTOS.h"
+#include "task.h"
+#include "semphr.h"
+#endif
+
+
+/******************************************************************************
+ DEFINE TYPES
+ ******************************************************************************/
+// Status bits - These are used to set/reset the corresponding bits in a given variable
+typedef enum{
+ STATUS_BIT_NWP_INIT = 0, // If this bit is set: Network Processor is
+ // powered up
+
+ STATUS_BIT_CONNECTION, // If this bit is set: the device is connected to
+ // the AP or client is connected to device (AP)
+
+ STATUS_BIT_IP_LEASED, // If this bit is set: the device has leased IP to
+ // any connected client
+
+ STATUS_BIT_IP_ACQUIRED, // If this bit is set: the device has acquired an IP
+
+ STATUS_BIT_SMARTCONFIG_START, // If this bit is set: the SmartConfiguration
+ // process is started from SmartConfig app
+
+ STATUS_BIT_P2P_DEV_FOUND, // If this bit is set: the device (P2P mode)
+ // found any p2p-device in scan
+
+ STATUS_BIT_P2P_REQ_RECEIVED, // If this bit is set: the device (P2P mode)
+ // found any p2p-negotiation request
+
+ STATUS_BIT_CONNECTION_FAILED, // If this bit is set: the device(P2P mode)
+ // connection to client(or reverse way) is failed
+
+ STATUS_BIT_PING_DONE // If this bit is set: the device has completed
+ // the ping operation
+}e_StatusBits;
+
+typedef struct _wlan_obj_t {
+ mp_obj_base_t base;
+ SlWlanMode_t mode;
+ uint32_t status;
+ uint8_t macAddr[SL_MAC_ADDR_LEN];
+ uint8_t ssid_name[33];
+ uint8_t bssid[6];
+ bool servers_enabled;
+
+ // IPVv4 data
+ uint32_t ip;
+ uint32_t gateway;
+ uint32_t dns;
+
+} wlan_obj_t;
+
+/******************************************************************************
+ DEFINE CONSTANTS
+ ******************************************************************************/
+#define CLR_STATUS_BIT_ALL(status) (status = 0)
+#define SET_STATUS_BIT(status, bit) (status |= ( 1 << (bit)))
+#define CLR_STATUS_BIT(status, bit) (status &= ~(1 << (bit)))
+#define GET_STATUS_BIT(status, bit) (0 != (status & (1 << (bit))))
+
+#define IS_NW_PROCSR_ON(status) GET_STATUS_BIT(status, STATUS_BIT_NWP_INIT)
+#define IS_CONNECTED(status) GET_STATUS_BIT(status, STATUS_BIT_CONNECTION)
+#define IS_IP_LEASED(status) GET_STATUS_BIT(status, STATUS_BIT_IP_LEASED)
+#define IS_IP_ACQUIRED(status) GET_STATUS_BIT(status, STATUS_BIT_IP_ACQUIRED)
+#define IS_SMART_CFG_START(status) GET_STATUS_BIT(status, STATUS_BIT_SMARTCONFIG_START)
+#define IS_P2P_DEV_FOUND(status) GET_STATUS_BIT(status, STATUS_BIT_P2P_DEV_FOUND)
+#define IS_P2P_REQ_RCVD(status) GET_STATUS_BIT(status, STATUS_BIT_P2P_REQ_RECEIVED)
+#define IS_CONNECT_FAILED(status) GET_STATUS_BIT(status, STATUS_BIT_CONNECTION_FAILED)
+#define IS_PING_DONE(status) GET_STATUS_BIT(status, STATUS_BIT_PING_DONE)
+
+#define MODWLAN_SL_SCAN_ENABLE 1
+#define MODWLAN_SL_SCAN_DISABLE 0
+#define MODWLAN_SL_MAX_NETWORKS 20
+
+#define MODWLAN_TIMEOUT_MS 5000
+#define MODWLAN_MAX_NETWORKS 20
+
+#define ASSERT_ON_ERROR( x ) ASSERT((x) >= 0 )
+
+#define IPV4_ADDR_STR_LEN_MAX (16)
+#define SL_STOP_TIMEOUT 500
+
+#define WLAN_MAX_RX_SIZE 16000
+
+#define MAKE_SOCKADDR(addr, ip, port) sockaddr addr; \
+ addr.sa_family = AF_INET; \
+ addr.sa_data[0] = port >> 8; \
+ addr.sa_data[1] = port; \
+ addr.sa_data[2] = ip[0]; \
+ addr.sa_data[3] = ip[1]; \
+ addr.sa_data[4] = ip[2]; \
+ addr.sa_data[5] = ip[3];
+
+#define UNPACK_SOCKADDR(addr, ip, port) port = (addr.sa_data[0] << 8) | addr.sa_data[1]; \
+ ip[0] = addr.sa_data[2]; \
+ ip[1] = addr.sa_data[3]; \
+ ip[2] = addr.sa_data[4]; \
+ ip[3] = addr.sa_data[5];
+
+/******************************************************************************
+ DECLARE PUBLIC DATA
+ ******************************************************************************/
+STATIC wlan_obj_t wlan_obj;
+
+/******************************************************************************
+ DECLARE EXPORTED DATA
+ ******************************************************************************/
+SemaphoreHandle_t xWlanSemaphore = NULL;
+
+/******************************************************************************
+ DECLARE PRIVATE FUNCTIONS
+ ******************************************************************************/
+STATIC void wlan_initialize_data (void);
+STATIC void wlan_reenable (SlWlanMode_t mode);
+STATIC void wlan_get_sl_mac (void);
+STATIC modwlan_Status_t wlan_do_connect (const char* ssid, uint32_t ssid_len, const char* bssid, uint8_t sec,
+ const char* key, uint32_t key_len);
+
+
+//*****************************************************************************
+//
+//! \brief The Function Handles WLAN Events
+//!
+//! \param[in] pWlanEvent - Pointer to WLAN Event Info
+//!
+//! \return None
+//!
+//*****************************************************************************
+void SimpleLinkWlanEventHandler(SlWlanEvent_t *pWlanEvent)
+{
+ if(!pWlanEvent) {
+ return;
+ }
+
+ switch(pWlanEvent->Event)
+ {
+ case SL_WLAN_CONNECT_EVENT:
+ {
+ SET_STATUS_BIT(wlan_obj.status, STATUS_BIT_CONNECTION);
+ //
+ // Information about the connected AP (like name, MAC etc) will be
+ // available in 'slWlanConnectAsyncResponse_t'-Applications
+ // can use it if required
+ //
+ slWlanConnectAsyncResponse_t *pEventData = &pWlanEvent->EventData.STAandP2PModeWlanConnected;
+
+ // Copy new connection SSID and BSSID to global parameters
+ memcpy(wlan_obj.ssid_name, pEventData->ssid_name, pEventData->ssid_len);
+ memcpy(wlan_obj.bssid, pEventData->bssid, SL_BSSID_LENGTH);
+ }
+ break;
+ case SL_WLAN_DISCONNECT_EVENT:
+ {
+ slWlanConnectAsyncResponse_t* pEventData = NULL;
+
+ CLR_STATUS_BIT(wlan_obj.status, STATUS_BIT_CONNECTION);
+ CLR_STATUS_BIT(wlan_obj.status, STATUS_BIT_IP_ACQUIRED);
+
+ pEventData = &pWlanEvent->EventData.STAandP2PModeDisconnected;
+
+ // If the user has initiated the 'Disconnect' request,
+ //'reason_code' is SL_USER_INITIATED_DISCONNECTION
+ if (SL_USER_INITIATED_DISCONNECTION == pEventData->reason_code) {
+
+ }
+ else {
+
+ }
+ memset(wlan_obj.ssid_name, 0, sizeof(wlan_obj.ssid_name));
+ memset(wlan_obj.bssid, 0, sizeof(wlan_obj.bssid));
+ }
+ break;
+ case SL_WLAN_STA_CONNECTED_EVENT:
+ break;
+ case SL_WLAN_STA_DISCONNECTED_EVENT:
+ break;
+ case SL_WLAN_P2P_DEV_FOUND_EVENT:
+ break;
+ case SL_WLAN_P2P_NEG_REQ_RECEIVED_EVENT:
+ break;
+ case SL_WLAN_CONNECTION_FAILED_EVENT:
+ break;
+ default:
+ break;
+ }
+}
+
+//*****************************************************************************
+//
+//! \brief This function handles network events such as IP acquisition, IP
+//! leased, IP released etc.
+//!
+//! \param[in] pNetAppEvent - Pointer to NetApp Event Info
+//!
+//! \return None
+//!
+//*****************************************************************************
+void SimpleLinkNetAppEventHandler(SlNetAppEvent_t *pNetAppEvent)
+{
+ if(!pNetAppEvent) {
+ return;
+ }
+
+ switch(pNetAppEvent->Event)
+ {
+ case SL_NETAPP_IPV4_IPACQUIRED_EVENT:
+ {
+ SlIpV4AcquiredAsync_t *pEventData = NULL;
+
+ SET_STATUS_BIT(wlan_obj.status, STATUS_BIT_IP_ACQUIRED);
+
+ // Ip Acquired Event Data
+ pEventData = &pNetAppEvent->EventData.ipAcquiredV4;
+
+ // Get the IP addresses
+ wlan_obj.gateway = ntohl(pEventData->gateway);
+ wlan_obj.ip = ntohl(pEventData->ip);
+ wlan_obj.dns = ntohl(pEventData->dns);
+ }
+ break;
+ case SL_NETAPP_IPV6_IPACQUIRED_EVENT:
+ break;
+ case SL_NETAPP_IP_LEASED_EVENT:
+ break;
+ case SL_NETAPP_IP_RELEASED_EVENT:
+ break;
+ default:
+ break;
+ }
+}
+
+
+//*****************************************************************************
+//
+//! \brief This function handles HTTP server events
+//!
+//! \param[in] pServerEvent - Contains the relevant event information
+//! \param[in] pServerResponse - Should be filled by the user with the
+//! relevant response information
+//!
+//! \return None
+//!
+//****************************************************************************
+void SimpleLinkHttpServerCallback(SlHttpServerEvent_t *pHttpEvent, SlHttpServerResponse_t *pHttpResponse)
+{
+ if (!pHttpEvent) {
+ return;
+ }
+
+ switch (pHttpEvent->Event) {
+ case SL_NETAPP_HTTPGETTOKENVALUE_EVENT:
+ break;
+ case SL_NETAPP_HTTPPOSTTOKENVALUE_EVENT:
+ break;
+ default:
+ break;
+ }
+}
+
+//*****************************************************************************
+//
+//! \brief This function handles General Events
+//!
+//! \param[in] pDevEvent - Pointer to General Event Info
+//!
+//! \return None
+//!
+//*****************************************************************************
+void SimpleLinkGeneralEventHandler(SlDeviceEvent_t *pDevEvent)
+{
+ if (!pDevEvent) {
+ return;
+ }
+
+ ASSERT (false);
+}
+
+
+//*****************************************************************************
+//
+//! This function handles socket events indication
+//!
+//! \param[in] pSock - Pointer to Socket Event Info
+//!
+//! \return None
+//!
+//*****************************************************************************
+void SimpleLinkSockEventHandler(SlSockEvent_t *pSock)
+{
+ if (!pSock) {
+ return;
+ }
+
+ switch( pSock->Event ) {
+ case SL_SOCKET_TX_FAILED_EVENT:
+ break;
+ default:
+ break;
+ }
+}
+
+//*****************************************************************************
+// SimpleLink Asynchronous Event Handlers -- End
+//*****************************************************************************
+
+void wlan_init0 (void) {
+ // Set the mode to an invalid one
+ wlan_obj.mode = -1;
+ wlan_obj.base.type = NULL;
+ memset (wlan_obj.macAddr, 0, SL_MAC_ADDR_LEN);
+#ifdef USE_FREERTOS
+ if (NULL == xWlanSemaphore) {
+ xWlanSemaphore = xSemaphoreCreateBinary();
+ }
+#endif
+ wlan_initialize_data ();
+}
+
+modwlan_Status_t wlan_sl_enable (SlWlanMode_t mode, const char *ssid, uint8_t ssid_len, uint8_t sec,
+ const char *key, uint8_t key_len, uint8_t channel) {
+
+ if (mode == ROLE_STA || mode == ROLE_AP || mode == ROLE_P2P) {
+ if (wlan_obj.mode < 0) {
+ wlan_obj.mode = sl_Start(0, 0, 0);
+ #ifdef USE_FREERTOS
+ xSemaphoreGive (xWlanSemaphore);
+ #endif
+ }
+
+ // get the mac address
+ wlan_get_sl_mac();
+
+ // stop the device if it's not in station mode
+ if (wlan_obj.mode != ROLE_STA) {
+ if (ROLE_AP == wlan_obj.mode) {
+ // if the device is in AP mode, we need to wait for this event
+ // before doing anything
+ while (!IS_IP_ACQUIRED(wlan_obj.status)) {
+ HAL_Delay (5);
+ }
+ }
+ // switch to STA mode
+ ASSERT_ON_ERROR(sl_WlanSetMode(ROLE_STA));
+ // stop and start again
+ wlan_reenable(ROLE_STA);
+ }
+
+ // Device in station-mode. Disconnect previous connection if any
+ // The function returns 0 if 'Disconnected done', negative number if already
+ // disconnected Wait for 'disconnection' event if 0 is returned, Ignore
+ // other return-codes
+ if (0 == sl_WlanDisconnect()) {
+ while (IS_CONNECTED (wlan_obj.status)) {
+ HAL_Delay (5);
+ }
+ }
+
+ // clear wlan data after checking any of the status flags
+ wlan_initialize_data ();
+
+ // Set connection policy to Auto + SmartConfig (Device's default connection policy)
+ ASSERT_ON_ERROR(sl_WlanPolicySet(SL_POLICY_CONNECTION, SL_CONNECTION_POLICY(1, 0, 0, 0, 1), NULL, 0));
+
+ // Remove all profiles
+ ASSERT_ON_ERROR(sl_WlanProfileDel(0xFF));
+
+ // Enable the DHCP client
+ uint8_t value = 1;
+ ASSERT_ON_ERROR(sl_NetCfgSet(SL_IPV4_STA_P2P_CL_DHCP_ENABLE, 1, 1, &value));
+
+ // Set PM policy to normal
+ ASSERT_ON_ERROR(sl_WlanPolicySet(SL_POLICY_PM, SL_NORMAL_POLICY, NULL, 0));
+
+ // Unregister mDNS services
+ ASSERT_ON_ERROR(sl_NetAppMDNSUnRegisterService(0, 0));
+
+ // Remove all 64 filters (8 * 8)
+ _WlanRxFilterOperationCommandBuff_t RxFilterIdMask;
+ memset ((void *)&RxFilterIdMask, 0 ,sizeof(RxFilterIdMask));
+ memset(RxFilterIdMask.FilterIdMask, 0xFF, 8);
+ ASSERT_ON_ERROR(sl_WlanRxFilterSet(SL_REMOVE_RX_FILTER, (_u8 *)&RxFilterIdMask, sizeof(_WlanRxFilterOperationCommandBuff_t)));
+
+ // Set Tx power level for station or AP mode
+ // Number between 0-15, as dB offset from max power - 0 will set max power
+ uint8_t ucPower = 0;
+ if (mode == ROLE_AP) {
+ // Disable the scanning
+ ASSERT_ON_ERROR(sl_WlanPolicySet(SL_POLICY_SCAN, MODWLAN_SL_SCAN_DISABLE, NULL, 0));
+
+ // Switch to AP mode
+ ASSERT_ON_ERROR(sl_WlanSetMode(mode));
+ ASSERT (ssid != NULL && key != NULL);
+ ASSERT_ON_ERROR(sl_WlanSet(SL_WLAN_CFG_GENERAL_PARAM_ID, WLAN_GENERAL_PARAM_OPT_AP_TX_POWER, sizeof(ucPower),
+ (unsigned char *)&ucPower));
+ ASSERT_ON_ERROR(sl_WlanSet(SL_WLAN_CFG_AP_ID, WLAN_AP_OPT_SSID, ssid_len, (unsigned char *)ssid));
+ ASSERT_ON_ERROR(sl_WlanSet(SL_WLAN_CFG_AP_ID, WLAN_AP_OPT_SECURITY_TYPE, sizeof(uint8_t), &sec));
+ ASSERT_ON_ERROR(sl_WlanSet(SL_WLAN_CFG_AP_ID, WLAN_AP_OPT_PASSWORD, key_len, (unsigned char *)key));
+ _u8* country = (_u8*)"EU";
+ ASSERT_ON_ERROR(sl_WlanSet(SL_WLAN_CFG_GENERAL_PARAM_ID, WLAN_GENERAL_PARAM_OPT_COUNTRY_CODE, 2, country));
+ ASSERT_ON_ERROR(sl_WlanSet(SL_WLAN_CFG_AP_ID, WLAN_AP_OPT_CHANNEL, 1, (_u8 *)&channel));
+
+ // Stop and start again
+ wlan_reenable(mode);
+ ASSERT (wlan_obj.mode == mode);
+
+ SlNetAppDhcpServerBasicOpt_t dhcpParams;
+ dhcpParams.lease_time = 4096; // lease time (in seconds) of the IP Address
+ dhcpParams.ipv4_addr_start = SL_IPV4_VAL(192,168,1,2); // first IP Address for allocation.
+ dhcpParams.ipv4_addr_last = SL_IPV4_VAL(192,168,1,254); // last IP Address for allocation.
+ ASSERT_ON_ERROR(sl_NetAppStop(SL_NET_APP_DHCP_SERVER_ID)); // Stop DHCP server before settings
+ ASSERT_ON_ERROR(sl_NetAppSet(SL_NET_APP_DHCP_SERVER_ID, NETAPP_SET_DHCP_SRV_BASIC_OPT,
+ sizeof(SlNetAppDhcpServerBasicOpt_t), (_u8* )&dhcpParams)); // set parameters
+ ASSERT_ON_ERROR(sl_NetAppStart(SL_NET_APP_DHCP_SERVER_ID)); // Start DHCP server with new settings
+
+ SlNetCfgIpV4Args_t ipV4;
+ ipV4.ipV4 = (_u32)SL_IPV4_VAL(192,168,1,1); // _u32 IP address
+ ipV4.ipV4Mask = (_u32)SL_IPV4_VAL(255,255,255,0); // _u32 Subnet mask for this AP
+ ipV4.ipV4Gateway = (_u32)SL_IPV4_VAL(192,168,1,1); // _u32 Default gateway address
+ ipV4.ipV4DnsServer = (_u32)SL_IPV4_VAL(192,168,1,1); // _u32 DNS server address
+ ASSERT_ON_ERROR(sl_NetCfgSet(SL_IPV4_AP_P2P_GO_STATIC_ENABLE, IPCONFIG_MODE_ENABLE_IPV4,
+ sizeof(SlNetCfgIpV4Args_t), (_u8 *)&ipV4));
+
+ // Stop and start again
+ wlan_reenable(mode);
+ }
+ // STA and P2P modes
+ else {
+ ASSERT_ON_ERROR(sl_WlanSet(SL_WLAN_CFG_GENERAL_PARAM_ID, WLAN_GENERAL_PARAM_OPT_STA_TX_POWER,
+ sizeof(ucPower), (unsigned char *)&ucPower));
+ // Enable scanning every 60 seconds
+ uint32_t scanSeconds = 60;
+ ASSERT_ON_ERROR(sl_WlanPolicySet(SL_POLICY_SCAN , MODWLAN_SL_SCAN_ENABLE, (_u8 *)&scanSeconds, sizeof(scanSeconds)));
+
+ if (mode == ROLE_P2P) {
+ // Switch to P2P mode
+ ASSERT_ON_ERROR(sl_WlanSetMode(mode));
+ // Stop and start again
+ wlan_reenable(mode);
+ }
+ }
+ return MODWLAN_OK;
+ }
+ return MODWLAN_ERROR_INVALID_PARAMS;
+}
+
+void wlan_sl_disable (void) {
+ if (wlan_obj.mode >= 0) {
+ #ifdef USE_FREERTOS
+ xSemaphoreTake (xWlanSemaphore, portMAX_DELAY);
+ #endif
+ wlan_obj.mode = -1;
+ ASSERT_ON_ERROR (sl_Stop(SL_STOP_TIMEOUT));
+ }
+}
+
+SlWlanMode_t wlan_get_mode (void) {
+ return wlan_obj.mode;
+}
+
+void wlan_get_mac (uint8_t *macAddress) {
+ if (macAddress) {
+ memcpy (macAddress, wlan_obj.macAddr, SL_MAC_ADDR_LEN);
+ }
+}
+
+void wlan_get_ip (uint32_t *ip) {
+ if (ip) {
+ *ip = IS_IP_ACQUIRED(wlan_obj.status) ? wlan_obj.ip : 0;
+ }
+}
+
+void wlan_set_pm_policy (uint8_t policy) {
+ ASSERT_ON_ERROR(sl_WlanPolicySet(SL_POLICY_PM, policy, NULL, 0));
+}
+
+void wlan_servers_stop (void) {
+ servers_disable();
+ do {
+ HAL_Delay (2);
+ } while (servers_are_enabled());
+}
+
+//*****************************************************************************
+// DEFINE STATIC FUNCTIONS
+//*****************************************************************************
+
+STATIC void wlan_initialize_data (void) {
+ wlan_obj.status = 0;
+ wlan_obj.dns = 0;
+ wlan_obj.gateway = 0;
+ wlan_obj.ip = 0;
+ memset(wlan_obj.ssid_name, 0, sizeof(wlan_obj.ssid_name));
+ memset(wlan_obj.bssid, 0, sizeof(wlan_obj.bssid));
+}
+
+STATIC void wlan_reenable (SlWlanMode_t mode) {
+ // Stop and start again
+ wlan_obj.mode = -1;
+#ifdef USE_FREERTOS
+ xSemaphoreTake (xWlanSemaphore, portMAX_DELAY);
+#endif
+ ASSERT_ON_ERROR(sl_Stop(SL_STOP_TIMEOUT));
+ wlan_obj.mode = sl_Start(0, 0, 0);
+#ifdef USE_FREERTOS
+ xSemaphoreGive (xWlanSemaphore);
+#endif
+ ASSERT (wlan_obj.mode == mode);
+}
+
+STATIC modwlan_Status_t wlan_do_connect (const char* ssid, uint32_t ssid_len, const char* bssid, uint8_t sec, const char* key, uint32_t key_len)
+{
+ SlSecParams_t secParams;
+
+ secParams.Key = (_i8*)key;
+ secParams.KeyLen = ((key != NULL) ? key_len : 0);
+ secParams.Type = sec;
+
+ if (0 == sl_WlanConnect((_i8*)ssid, ssid_len, (_u8*)bssid, &secParams, NULL)) {
+
+ // Wait for WLAN Event
+ uint32_t waitForConnectionMs = 0;
+ while (!IS_CONNECTED(wlan_obj.status)) {
+ HAL_Delay (5);
+ if (++waitForConnectionMs >= MODWLAN_TIMEOUT_MS) {
+ return MODWLAN_ERROR_TIMEOUT;
+ }
+ }
+
+ return MODWLAN_OK;
+ }
+
+ return MODWLAN_ERROR_INVALID_PARAMS;
+}
+
+STATIC void wlan_get_sl_mac (void) {
+ // Get the MAC address
+ uint8_t macAddrLen = SL_MAC_ADDR_LEN;
+ sl_NetCfgGet(SL_MAC_ADDRESS_GET,NULL, &macAddrLen, wlan_obj.macAddr);
+}
+
+/// \method init(mode, ssid=myWlan, security=wlan.WPA_WPA2, key=myWlanKey)
+///
+/// Initialise the UART bus with the given parameters:
+///
+/// - `mode` can be ROLE_AP, ROLE_STA and ROLE_P2P.
+/// - `ssid` is the network ssid in case of AP mode
+/// - `security` is the security type for AP mode
+/// - `key` is the key when in AP mode
+/// - `channel` is the channel to use for the AP network
+STATIC const mp_arg_t wlan_init_args[] = {
+ { MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = ROLE_STA} },
+ { MP_QSTR_ssid, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
+ { MP_QSTR_security, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = SL_SEC_TYPE_OPEN} },
+ { MP_QSTR_key, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
+ { MP_QSTR_channel, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 5} },
+};
+
+STATIC mp_obj_t wlan_init_helper(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+ // parse args
+ mp_arg_val_t args[MP_ARRAY_SIZE(wlan_init_args)];
+ mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(wlan_init_args), wlan_init_args, args);
+
+ // get the ssid
+ mp_uint_t ssid_len;
+ const char *ssid = mp_obj_str_get_data(args[1].u_obj, &ssid_len);
+
+ // get the key
+ mp_uint_t key_len;
+ const char *key = mp_obj_str_get_data(args[3].u_obj, &key_len);
+
+ if (key_len < 8) {
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, mpexception_value_invalid_arguments));
+ }
+
+ // Force the channel to be between 1-11
+ uint8_t channel = args[4].u_int > 0 ? args[4].u_int % 12 : 1;
+
+ if (MODWLAN_OK != wlan_sl_enable (args[0].u_int, ssid, ssid_len, args[2].u_int, key, key_len, channel)) {
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_operation_failed));
+ }
+
+ return mp_const_none;
+}
+
+
+/******************************************************************************/
+// Micro Python bindings; WLAN class
+
+/// \class WLAN - driver for the WLAN functionality of the SoC
+
+/// \classmethod \constructor()
+/// Create a wlan obecjt and initialise the simplelink engine
+//
+STATIC mp_obj_t wlan_make_new (mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
+ // check arguments
+ mp_arg_check_num(n_args, n_kw, 0, MP_ARRAY_SIZE(wlan_init_args), true);
+
+ if (n_args > 0) {
+ // Get the mode
+ SlWlanMode_t mode = mp_obj_get_int(args[0]);
+
+ // Stop all other processes using the wlan engine
+ if ( (wlan_obj.servers_enabled = servers_are_enabled()) ) {
+ wlan_servers_stop();
+ }
+ if (mode == ROLE_AP) {
+ // start the peripheral
+ mp_map_t kw_args;
+ mp_map_init_fixed_table(&kw_args, n_kw, args + n_args);
+ wlan_init_helper(n_args, args, &kw_args);
+ }
+ // TODO: Only STA mode supported for the moment. What if P2P?
+ else if (n_args == 1) {
+ if (MODWLAN_OK != wlan_sl_enable (mode, NULL, 0, 0, NULL, 0, 0)) {
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_operation_failed));
+ }
+ }
+ else {
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, mpexception_num_type_invalid_arguments));
+ }
+
+ // Start the servers again
+ if (wlan_obj.servers_enabled) {
+ servers_enable ();
+ }
+ } else if (wlan_obj.mode < 0) {
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, mpexception_num_type_invalid_arguments));
+ }
+
+ wlan_obj.base.type = (mp_obj_type_t*)&mod_network_nic_type_wlan;
+ // register with the network module
+ mod_network_register_nic(&wlan_obj);
+
+ return &wlan_obj;
+}
+
+STATIC void wlan_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
+ wlan_obj_t *self = self_in;
+ print(env, "wlan(mode=%u, status=%u", self->mode, self->status);
+ print(env, ", mac=%02x:%02x:%02x:%02x:%02x:%02x", self->macAddr[0], self->macAddr[1], self->macAddr[2],
+ self->macAddr[3], self->macAddr[4], self->macAddr[5]);
+
+ // Only print the ssid if in station or ap mode
+ if (self->mode == ROLE_STA || self->mode == ROLE_AP) {
+ print(env, ", ssid=%s", self->ssid_name);
+
+ // Only print the bssid if in station mode
+ if (self->mode == ROLE_STA) {
+ print(env, ", bssid=%02x:%02x:%02x:%02x:%02x:%02x", self->bssid[0], self->bssid[1], self->bssid[2],
+ self->bssid[3], self->bssid[4], self->bssid[5]);
+ }
+
+ char ip_str[IPV4_ADDR_STR_LEN_MAX];
+ uint8_t *ip = (uint8_t *)&self->ip;
+ snprintf(ip_str, 16, "%u.%u.%u.%u", ip[0], ip[1], ip[2], ip[3]);
+ print(env, ", ip=%s", ip_str);
+ ip = (uint8_t *)&self->gateway;
+ snprintf(ip_str, 16, "%u.%u.%u.%u", ip[0], ip[1], ip[2], ip[3]);
+ print(env, ", gateway=%s", ip_str);
+ ip = (uint8_t *)&self->dns;
+ snprintf(ip_str, 16, "%u.%u.%u.%u", ip[0], ip[1], ip[2], ip[3]);
+ print(env, ", dns=%s)", ip_str);
+ }
+ else {
+ print(env, ")");
+ }
+}
+
+/// \method mode()
+/// Get the wlan mode:
+///
+/// - Returns the current wlan mode. Possible values are:
+/// ROLE_STA, ROLE_AP and ROLE_P2P
+///
+STATIC mp_obj_t wlan_getmode(mp_obj_t self_in) {
+ wlan_obj_t* self = self_in;
+ return mp_obj_new_int(self->mode);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(wlan_getmode_obj, wlan_getmode);
+
+STATIC mp_obj_t wlan_setpm(mp_obj_t self_in, mp_obj_t pm_mode) {
+ mp_int_t mode = mp_obj_get_int(pm_mode);
+ if (mode < SL_NORMAL_POLICY || mode > SL_LONG_SLEEP_INTERVAL_POLICY) {
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
+ }
+ wlan_set_pm_policy((uint8_t)mode);
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(wlan_setpm_obj, wlan_setpm);
+
+/// \method connect(ssid, key=None, *, security=OPEN, bssid=None)
+STATIC mp_obj_t wlan_connect(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+ STATIC const mp_arg_t allowed_args[] = {
+ { MP_QSTR_ssid, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
+ { MP_QSTR_key, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
+ { MP_QSTR_security, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = SL_SEC_TYPE_OPEN} },
+ { 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);
+
+ // get ssid
+ mp_uint_t ssid_len;
+ const char *ssid = mp_obj_str_get_data(args[0].u_obj, &ssid_len);
+
+ // get key and sec
+ mp_uint_t key_len = 0;
+ const char *key = NULL;
+ mp_uint_t sec = SL_SEC_TYPE_OPEN;
+ if (args[1].u_obj != mp_const_none) {
+ key = mp_obj_str_get_data(args[1].u_obj, &key_len);
+ sec = args[2].u_int;
+ }
+
+ // get bssid
+ const char *bssid = NULL;
+ if (args[3].u_obj != mp_const_none) {
+ bssid = mp_obj_str_get_str(args[3].u_obj);
+ }
+
+ if (wlan_obj.mode != ROLE_STA) {
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_request_not_possible));
+ }
+ else {
+ if (GET_STATUS_BIT(wlan_obj.status, STATUS_BIT_CONNECTION)) {
+ if (0 == sl_WlanDisconnect()) {
+ while (IS_CONNECTED(wlan_obj.status)) {
+ HAL_Delay (5);
+ }
+ }
+ }
+ // connect to the requested access point
+ modwlan_Status_t status;
+ status = wlan_do_connect (ssid, ssid_len, bssid, sec, key, key_len);
+ if (status != MODWLAN_OK) {
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_operation_failed));
+ }
+ }
+
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_KW(wlan_connect_obj, 1, wlan_connect);
+
+/// \method wlan_disconnect()
+/// Closes the current WLAN connection
+///
+STATIC mp_obj_t wlan_disconnect(mp_obj_t self_in) {
+ sl_WlanDisconnect();
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(wlan_disconnect_obj, wlan_disconnect);
+
+/// \method is_connected()
+/// Returns true if connected to the AP and an IP address has been assigned. False otherwise.
+///
+STATIC mp_obj_t wlan_isconnected(mp_obj_t self_in) {
+ if (GET_STATUS_BIT(wlan_obj.status, STATUS_BIT_CONNECTION) &&
+ GET_STATUS_BIT(wlan_obj.status, STATUS_BIT_IP_ACQUIRED)) {
+ return mp_const_true;
+ }
+ return mp_const_false;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(wlan_isconnected_obj, wlan_isconnected);
+
+/// \method getip()
+/// Get the IP
+///
+/// - Returns the acquired IP address
+///
+STATIC mp_obj_t wlan_getip(mp_obj_t self_in) {
+ return mod_network_format_ipv4_addr ((uint8_t *)&wlan_obj.ip);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(wlan_getip_obj, wlan_getip);
+
+
+/// \method wlan_netlist()
+/// Returns a list of tuples with all the acces points within range
+STATIC mp_obj_t wlan_scan(mp_obj_t self_in) {
+ Sl_WlanNetworkEntry_t wlanEntry;
+ uint8_t _index = 0;
+ mp_obj_t nets = NULL;
+
+ do {
+ if (sl_WlanGetNetworkList(_index++, 1, &wlanEntry) <= 0) {
+ break;
+ }
+ mp_obj_t tuple[4];
+
+ tuple[0] = mp_obj_new_str((const char *)wlanEntry.ssid, wlanEntry.ssid_len, false);
+ tuple[1] = mp_obj_new_str((const char *)wlanEntry.bssid, SL_BSSID_LENGTH, false);
+ // 'Normalize' the security type
+ if (wlanEntry.sec_type > 2) {
+ wlanEntry.sec_type = 2;
+ }
+ tuple[2] = mp_obj_new_int(wlanEntry.sec_type);
+ tuple[3] = mp_obj_new_int(wlanEntry.rssi);
+
+ if (_index == 1) {
+ // Initialize the set
+ nets = mp_obj_new_set(0, NULL);
+ }
+ // Add the network found to the list if it's unique
+ mp_obj_set_store(nets, mp_obj_new_tuple(4, tuple));
+
+ } while (_index < MODWLAN_SL_MAX_NETWORKS);
+
+ return (nets != NULL) ? nets : mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(wlan_scan_obj, wlan_scan);
+
+STATIC mp_obj_t wlan_serversstart(mp_obj_t self_in) {
+ servers_enable();
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(wlan_serversstart_obj, wlan_serversstart);
+
+STATIC mp_obj_t wlan_serversstop(mp_obj_t self_in) {
+ wlan_servers_stop();
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(wlan_serversstop_obj, wlan_serversstop);
+
+STATIC mp_obj_t wlan_areserversenabled(mp_obj_t self_in) {
+ return MP_BOOL(servers_are_enabled());
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(wlan_areserversenabled_obj, wlan_areserversenabled);
+
+STATIC mp_obj_t wlan_serversuserpass(mp_obj_t self_in, mp_obj_t user, mp_obj_t pass) {
+ const char *_user = mp_obj_str_get_str(user);
+ const char *_pass = mp_obj_str_get_str(pass);
+ servers_set_user_pass((char *)_user, (char *)_pass);
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_3(wlan_serversuserpass_obj, wlan_serversuserpass);
+
+STATIC const mp_map_elem_t wlan_locals_dict_table[] = {
+ { MP_OBJ_NEW_QSTR(MP_QSTR_connect), (mp_obj_t)&wlan_connect_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_getmode), (mp_obj_t)&wlan_getmode_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_setpm), (mp_obj_t)&wlan_setpm_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_scan), (mp_obj_t)&wlan_scan_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_disconnect), (mp_obj_t)&wlan_disconnect_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_isconnected), (mp_obj_t)&wlan_isconnected_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_getip), (mp_obj_t)&wlan_getip_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_serversstart), (mp_obj_t)&wlan_serversstart_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_serversstop), (mp_obj_t)&wlan_serversstop_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_areserversenabled), (mp_obj_t)&wlan_areserversenabled_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_serversuserpass), (mp_obj_t)&wlan_serversuserpass_obj },
+
+ // class constants
+ { MP_OBJ_NEW_QSTR(MP_QSTR_OPEN), MP_OBJ_NEW_SMALL_INT(SL_SEC_TYPE_OPEN) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_WEP), MP_OBJ_NEW_SMALL_INT(SL_SEC_TYPE_WEP) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_WPA_WPA2), MP_OBJ_NEW_SMALL_INT(SL_SEC_TYPE_WPA_WPA2) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_WPA_ENT), MP_OBJ_NEW_SMALL_INT(SL_SEC_TYPE_WPA_ENT) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_WPS_PBC), MP_OBJ_NEW_SMALL_INT(SL_SEC_TYPE_WPS_PBC) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_WPS_PIN), MP_OBJ_NEW_SMALL_INT(SL_SEC_TYPE_WPS_PIN) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_STA), MP_OBJ_NEW_SMALL_INT(ROLE_STA) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_AP), MP_OBJ_NEW_SMALL_INT(ROLE_AP) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_P2P), MP_OBJ_NEW_SMALL_INT(ROLE_P2P) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_NORMAL_PM), MP_OBJ_NEW_SMALL_INT(SL_NORMAL_POLICY) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_LOW_LATENCY_PM), MP_OBJ_NEW_SMALL_INT(SL_LOW_LATENCY_POLICY) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_LOW_POWER_PM), MP_OBJ_NEW_SMALL_INT(SL_LOW_POWER_POLICY) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_ALWAYS_ON_PM), MP_OBJ_NEW_SMALL_INT(SL_ALWAYS_ON_POLICY) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_LONG_SLEEP_PM), MP_OBJ_NEW_SMALL_INT(SL_LONG_SLEEP_INTERVAL_POLICY) },
+};
+STATIC MP_DEFINE_CONST_DICT(wlan_locals_dict, wlan_locals_dict_table);
+
+
+/******************************************************************************/
+// Micro Python bindings; WLAN socket
+
+STATIC int wlan_gethostbyname(mp_obj_t nic, const char *name, mp_uint_t len, uint8_t *out_ip, uint8_t family) {
+ uint32_t ip;
+ int result = sl_NetAppDnsGetHostByName((_i8 *)name, (_u16)len, (_u32*)&ip, (_u8)family);
+
+ out_ip[0] = ip >> 24;
+ out_ip[1] = ip >> 16;
+ out_ip[2] = ip >> 8;
+ out_ip[3] = ip;
+
+ return result;
+}
+
+STATIC int wlan_socket_socket(struct _mod_network_socket_obj_t *s, int *_errno) {
+ // open the socket
+ int16_t sd = sl_Socket(s->u_param.domain, s->u_param.type, s->u_param.proto);
+ if (s->sd < 0) {
+ *_errno = s->sd;
+ return -1;
+ }
+
+ // mark the socket not closed
+ s->closed = false;
+ // save the socket descriptor
+ s->sd = sd;
+
+ // make it blocking by default
+ int32_t optval = 0;
+ sl_SetSockOpt(sd, SOL_SOCKET, SO_NONBLOCKING, &optval, (SlSocklen_t)sizeof(optval));
+
+ return 0;
+}
+
+STATIC void wlan_socket_close(mod_network_socket_obj_t *s) {
+ s->closed = true;
+ sl_Close(s->sd);
+}
+
+STATIC int wlan_socket_bind(mod_network_socket_obj_t *s, byte *ip, mp_uint_t port, int *_errno) {
+ MAKE_SOCKADDR(addr, ip, port)
+ int ret = sl_Bind(s->sd, &addr, sizeof(addr));
+ if (ret != 0) {
+ *_errno = ret;
+ return -1;
+ }
+ return 0;
+}
+
+STATIC int wlan_socket_listen(mod_network_socket_obj_t *s, mp_int_t backlog, int *_errno) {
+ int ret = sl_Listen(s->sd, backlog);
+ if (ret != 0) {
+ *_errno = ret;
+ return -1;
+ }
+ return 0;
+}
+
+STATIC int wlan_socket_accept(mod_network_socket_obj_t *s, mod_network_socket_obj_t *s2, byte *ip, mp_uint_t *port, int *_errno) {
+ // accept incoming connection
+ int16_t sd;
+ sockaddr addr;
+ socklen_t addr_len = sizeof(addr);
+ if ((sd = sl_Accept(s->sd, &addr, &addr_len)) < 0) {
+ *_errno = sd;
+ return -1;
+ }
+
+ // Mark the socket not closed and save the new descriptor
+ s2->closed = false;
+ s2->sd = sd;
+
+ // return ip and port
+ UNPACK_SOCKADDR(addr, ip, *port);
+
+ return 0;
+}
+
+STATIC int wlan_socket_connect(mod_network_socket_obj_t *s, byte *ip, mp_uint_t port, int *_errno) {
+ MAKE_SOCKADDR(addr, ip, port)
+ int ret = sl_Connect(s->sd, &addr, sizeof(addr));
+ if (ret != 0) {
+ *_errno = ret;
+ return -1;
+ }
+ return 0;
+}
+
+STATIC int wlan_socket_send(mod_network_socket_obj_t *s, const byte *buf, mp_uint_t len, int *_errno) {
+ if (s->closed) {
+ sl_Close (s->sd);
+ *_errno = EBADF;
+ return -1;
+ }
+
+ mp_int_t bytes = 0;
+ if (len > 0) {
+ bytes = sl_Send(s->sd, (const void *)buf, len, 0);
+ }
+ if (bytes <= 0) {
+ *_errno = bytes;
+ return -1;
+ }
+
+ return bytes;
+}
+
+STATIC int wlan_socket_recv(mod_network_socket_obj_t *s, byte *buf, mp_uint_t len, int *_errno) {
+ // check if the socket is open
+ if (s->closed) {
+ // socket is closed, but the CC3200 may have some data remaining in its buffer, so check
+ fd_set rfds;
+ FD_ZERO(&rfds);
+ FD_SET(s->sd, &rfds);
+ timeval tv;
+ tv.tv_sec = 0;
+ tv.tv_usec = 2;
+ int nfds = sl_Select(s->sd + 1, &rfds, NULL, NULL, &tv);
+ if (nfds == -1 || !FD_ISSET(s->sd, &rfds)) {
+ // no data waiting, so close socket and return 0 data
+ sl_Close(s->sd);
+ return 0;
+ }
+ }
+
+ // cap length at WLAN_MAX_RX_SIZE
+ len = MIN(len, WLAN_MAX_RX_SIZE);
+
+ // do the recv
+ int ret = sl_Recv(s->sd, buf, len, 0);
+ if (ret < 0) {
+ *_errno = ret;
+ return -1;
+ }
+
+ return ret;
+}
+
+STATIC int wlan_socket_sendto( mod_network_socket_obj_t *s, const byte *buf, mp_uint_t len, byte *ip, mp_uint_t port, int *_errno) {
+ MAKE_SOCKADDR(addr, ip, port)
+ int ret = sl_SendTo(s->sd, (byte*)buf, len, 0, (sockaddr*)&addr, sizeof(addr));
+ if (ret < 0) {
+ *_errno = ret;
+ return -1;
+ }
+ return ret;
+}
+
+STATIC int wlan_socket_recvfrom(mod_network_socket_obj_t *s, byte *buf, mp_uint_t len, byte *ip, mp_uint_t *port, int *_errno) {
+ sockaddr addr;
+ socklen_t addr_len = sizeof(addr);
+ mp_int_t ret = sl_RecvFrom(s->sd, buf, len, 0, &addr, &addr_len);
+ if (ret < 0) {
+ *_errno = ret;
+ return -1;
+ }
+ UNPACK_SOCKADDR(addr, ip, *port);
+ return ret;
+}
+
+STATIC int wlan_socket_setsockopt(mod_network_socket_obj_t *socket, mp_uint_t level, mp_uint_t opt, const void *optval, mp_uint_t optlen, int *_errno) {
+ int ret = sl_SetSockOpt(socket->sd, level, opt, optval, optlen);
+ if (ret < 0) {
+ *_errno = ret;
+ return -1;
+ }
+ return 0;
+}
+
+STATIC int wlan_socket_settimeout(mod_network_socket_obj_t *s, mp_uint_t timeout_ms, int *_errno) {
+ int ret;
+ if (timeout_ms == 0 || timeout_ms == -1) {
+ int optval;
+ if (timeout_ms == 0) {
+ // set non-blocking mode
+ optval = 1;
+ } else {
+ // set blocking mode
+ optval = 0;
+ }
+ ret = sl_SetSockOpt(s->sd, SOL_SOCKET, SO_NONBLOCKING, &optval, sizeof(optval));
+ } else {
+ // set timeout
+ ret = sl_SetSockOpt(s->sd, SOL_SOCKET, SO_RCVTIMEO, &timeout_ms, sizeof(timeout_ms));
+ }
+
+ if (ret != 0) {
+ *_errno = ret;
+ return -1;
+ }
+
+ return 0;
+}
+
+STATIC int wlan_socket_ioctl (mod_network_socket_obj_t *s, mp_uint_t request, mp_uint_t arg, int *_errno) {
+ mp_int_t ret;
+ if (request == MP_IOCTL_POLL) {
+ mp_uint_t flags = arg;
+ ret = 0;
+ int32_t sd = s->sd;
+
+ // init fds
+ fd_set rfds, wfds, xfds;
+ FD_ZERO(&rfds);
+ FD_ZERO(&wfds);
+ FD_ZERO(&xfds);
+
+ // set fds if needed
+ if (flags & MP_IOCTL_POLL_RD) {
+ FD_SET(sd, &rfds);
+
+ // A socked that just closed is available for reading. A call to
+ // recv() returns 0 which is consistent with BSD.
+ if (s->closed) {
+ ret |= MP_IOCTL_POLL_RD;
+ }
+ }
+ if (flags & MP_IOCTL_POLL_WR) {
+ FD_SET(sd, &wfds);
+ }
+ if (flags & MP_IOCTL_POLL_HUP) {
+ FD_SET(sd, &xfds);
+ }
+
+ // call simplelink select with minimum timeout
+ SlTimeval_t tv;
+ tv.tv_sec = 0;
+ tv.tv_usec = 1;
+ int32_t nfds = sl_Select(sd + 1, &rfds, &wfds, &xfds, &tv);
+
+ // check for error
+ if (nfds == -1) {
+ *_errno = nfds;
+ return -1;
+ }
+
+ // check return of select
+ if (FD_ISSET(sd, &rfds)) {
+ ret |= MP_IOCTL_POLL_RD;
+ }
+ if (FD_ISSET(sd, &wfds)) {
+ ret |= MP_IOCTL_POLL_WR;
+ }
+ if (FD_ISSET(sd, &xfds)) {
+ ret |= MP_IOCTL_POLL_HUP;
+ }
+ } else {
+ *_errno = EINVAL;
+ ret = -1;
+ }
+ return ret;
+}
+
+const mod_network_nic_type_t mod_network_nic_type_wlan = {
+ .base = {
+ { &mp_type_type },
+ .name = MP_QSTR_WLAN,
+ .print = wlan_print,
+ .make_new = wlan_make_new,
+ .locals_dict = (mp_obj_t)&wlan_locals_dict,
+ },
+ .gethostbyname = wlan_gethostbyname,
+ .socket = wlan_socket_socket,
+ .close = wlan_socket_close,
+ .bind = wlan_socket_bind,
+ .listen = wlan_socket_listen,
+ .accept = wlan_socket_accept,
+ .connect = wlan_socket_connect,
+ .send = wlan_socket_send,
+ .recv = wlan_socket_recv,
+ .sendto = wlan_socket_sendto,
+ .recvfrom = wlan_socket_recvfrom,
+ .setsockopt = wlan_socket_setsockopt,
+ .settimeout = wlan_socket_settimeout,
+ .ioctl = wlan_socket_ioctl,
+};
diff --git a/cc3200/mods/modwlan.h b/cc3200/mods/modwlan.h
new file mode 100644
index 000000000..7a84f2a51
--- /dev/null
+++ b/cc3200/mods/modwlan.h
@@ -0,0 +1,71 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2015 Daniel Campora
+ *
+ * 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 SIMPLELINKTASK_H_
+#define SIMPLELINKTASK_H_
+
+/******************************************************************************
+ DEFINE CONSTANTS
+ ******************************************************************************/
+#define SIMPLELINK_SPAWN_TASK_PRIORITY 3
+#define SIMPLELINK_TASK_STACK_SIZE 2048
+
+/******************************************************************************
+ DEFINE TYPES
+ ******************************************************************************/
+typedef enum
+{
+ MODWLAN_OK = 0,
+ MODWLAN_ERROR_INVALID_PARAMS = -1,
+ MODWLAN_ERROR_TIMEOUT = -2,
+ MODWLAN_ERROR_UNKNOWN = -3
+
+}modwlan_Status_t;
+
+/******************************************************************************
+ DECLARE PUBLIC DATA
+ ******************************************************************************/
+#ifdef USE_FREERTOS
+#include "FreeRTOS.h"
+#include "task.h"
+#include "semphr.h"
+extern SemaphoreHandle_t xWlanSemaphore;
+#endif
+
+/******************************************************************************
+ DECLARE PUBLIC FUNCTIONS
+ ******************************************************************************/
+extern void wlan_init0 (void);
+extern modwlan_Status_t wlan_sl_enable (SlWlanMode_t mode, const char *ssid, uint8_t ssid_len, uint8_t sec,
+ const char *key, uint8_t key_len, uint8_t channel);
+extern void wlan_sl_disable (void);
+extern SlWlanMode_t wlan_get_mode (void);
+extern void wlan_get_mac (uint8_t *macAddress);
+extern void wlan_get_ip (uint32_t *ip);
+extern void wlan_set_pm_policy (uint8_t policy);
+extern void wlan_servers_stop (void);
+
+#endif /* SIMPLELINKTASK_H_ */
diff --git a/cc3200/mods/pybextint.c b/cc3200/mods/pybextint.c
new file mode 100644
index 000000000..abfec5572
--- /dev/null
+++ b/cc3200/mods/pybextint.c
@@ -0,0 +1,357 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2013, 2014 Damien P. George
+ * Copyright (c) 2015 Daniel Campora
+ *
+ * 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 <stddef.h>
+#include <string.h>
+
+#include "mpconfig.h"
+#include MICROPY_HAL_H
+#include "py/nlr.h"
+#include "misc.h"
+#include "qstr.h"
+#include "py/runtime.h"
+#include "py/gc.h"
+#include "py/pfenv.h"
+#include "py/objlist.h"
+#include "inc/hw_types.h"
+#include "inc/hw_gpio.h"
+#include "inc/hw_ints.h"
+#include "inc/hw_memmap.h"
+#include "rom_map.h"
+#include "pin.h"
+#include "gpio.h"
+#include "pybgpio.h"
+#include "pybextint.h"
+#include "mpexception.h"
+#include "interrupt.h"
+#include "mpstate.h"
+#include "cc3200_asm.h"
+
+/// \moduleref pyb
+/// \class ExtInt - configure I/O pins to interrupt on external events
+///
+/// There are a maximum of 25 GPIO interrupt lines.
+///
+/// Example callback:
+///
+/// def callback(line):
+/// print(line.pin())
+///
+/// Note: ExtInt will automatically configure the gpio line as an input.
+///
+/// extint = pyb.ExtInt('GPIO10', pyb.ExtInt.IRQ_FALLING, pyb.GPIO.STD_PU, callback)
+///
+/// Now every time a falling edge is seen on the gpio pin, the callback will be
+/// called. Caution: mechanical pushbuttons have "bounce" and pushing or
+/// releasing a switch will often generate multiple edges.
+/// See: http://www.eng.utah.edu/~cs5780/debouncing.pdf for a detailed
+/// explanation, along with various techniques for debouncing.
+///
+/// All gpio objects go through the gpio mapper to come up with one of the
+/// gpio pins.
+///
+/// extint = pyb.ExtInt(gpio, mode, pull, callback)
+///
+/// There is also a C API, so that drivers which require EXTI interrupt lines
+/// can also use this code. See pybextint.h for the available functions.
+
+STATIC void ExecuteIntCallback (extint_obj_t *self);
+STATIC void GPIOA0IntHandler (void);
+STATIC void GPIOA1IntHandler (void);
+STATIC void GPIOA2IntHandler (void);
+STATIC void GPIOA3IntHandler (void);
+STATIC void EXTI_Handler(uint port);
+
+STATIC extint_obj_t* extint_add (uint pin_num, uint port, uint bit) {
+ extint_obj_t *self = m_new_obj(extint_obj_t);
+
+ self->port = port;
+ self->bit = bit;
+ self->callback = NULL;
+ self->pin_num = pin_num;
+ // add it to the list
+ mp_obj_list_append(&MP_STATE_PORT(pyb_extint_list), self);
+
+ return self;
+}
+
+STATIC extint_obj_t* extint_find (uint port, uint8_t bit) {
+ for (mp_uint_t i = 0; i < MP_STATE_PORT(pyb_extint_list).len; i++) {
+ extint_obj_t *self = (extint_obj_t *)MP_STATE_PORT(pyb_extint_list).items[i];
+ if (self->port == port && self->bit == bit) {
+ return self;
+ }
+ }
+ return NULL;
+}
+
+/// \method line()
+/// Return the pin number to which this external interrupt is mapped to.
+STATIC mp_obj_t extint_obj_pin(mp_obj_t self_in) {
+ extint_obj_t *self = self_in;
+ return MP_OBJ_NEW_SMALL_INT(self->pin_num);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(extint_obj_pin_obj, extint_obj_pin);
+
+/// \method enable()
+/// Enable a disabled interrupt.
+STATIC mp_obj_t extint_obj_enable(mp_obj_t self_in) {
+ extint_obj_t *self = self_in;
+ extint_enable(self);
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(extint_obj_enable_obj, extint_obj_enable);
+
+/// \method disable()
+/// Disable the interrupt associated with the ExtInt object.
+/// This could be useful for debouncing.
+STATIC mp_obj_t extint_obj_disable(mp_obj_t self_in) {
+ extint_obj_t *self = self_in;
+ extint_disable(self);
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(extint_obj_disable_obj, extint_obj_disable);
+
+/// \method swint()
+/// Trigger the callback from software.
+STATIC mp_obj_t extint_obj_swint(mp_obj_t self_in) {
+ extint_obj_t *self = self_in;
+ extint_swint(self);
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(extint_obj_swint_obj, extint_obj_swint);
+
+/// \classmethod \constructor(pin, mode, pull, callback)
+/// Create an ExtInt object:
+///
+/// - `gpio` is the gpio on which to enable the interrupt (can be a gpio object or any valid gpio name).
+/// - `mode` can be one of:
+/// - `ExtInt.IRQ_RISING` - trigger on a rising edge;
+/// - `ExtInt.IRQ_FALLING` - trigger on a falling edge;
+/// - `ExtInt.IRQ_RISING_FALLING` - trigger on a rising or falling edge.
+/// - `pull` can be one of:
+/// - `pyb.Pin.PULL_NONE` - no pull up or down resistors;
+/// - `pyb.Pin.PULL_UP` - enable the pull-up resistor;
+/// - `pyb.Pin.PULL_DOWN` - enable the pull-down resistor.
+/// - `callback` is the function to call when the interrupt triggers. The
+/// callback function must accept exactly 1 argument, which is the line that
+/// triggered the interrupt.
+STATIC const mp_arg_t pyb_extint_make_new_args[] = {
+ { MP_QSTR_gpio, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
+ { MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} },
+ { MP_QSTR_pull, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} },
+ { MP_QSTR_callback, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
+};
+#define PYB_EXTINT_MAKE_NEW_NUM_ARGS MP_ARRAY_SIZE(pyb_extint_make_new_args)
+
+STATIC mp_obj_t extint_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
+ // parse args
+ mp_arg_val_t vals[PYB_EXTINT_MAKE_NEW_NUM_ARGS];
+ mp_arg_parse_all_kw_array(n_args, n_kw, args, PYB_EXTINT_MAKE_NEW_NUM_ARGS, pyb_extint_make_new_args, vals);
+
+ extint_obj_t *self = extint_register(vals[0].u_obj, vals[1].u_int, vals[2].u_int, vals[3].u_obj);
+ self->base.type = type_in;
+
+ return self;
+}
+
+STATIC void extint_obj_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
+ extint_obj_t *self = self_in;
+ print(env, "<ExtInt pin=%u>", self->pin_num);
+}
+
+STATIC const mp_map_elem_t extint_locals_dict_table[] = {
+ { MP_OBJ_NEW_QSTR(MP_QSTR_pin), (mp_obj_t)&extint_obj_pin_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_enable), (mp_obj_t)&extint_obj_enable_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_disable), (mp_obj_t)&extint_obj_disable_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_swint), (mp_obj_t)&extint_obj_swint_obj },
+
+ // class constants
+ /// \constant IRQ_RISING - interrupt on a rising edge
+ /// \constant IRQ_FALLING - interrupt on a falling edge
+ /// \constant IRQ_RISING_FALLING - interrupt on a rising or falling edge
+ /// \constant IRQ_LOW_LEVEL - interrupt on a low level
+ /// \constant IRQ_HIGH_LEVEL - interrupt on a high level
+ { MP_OBJ_NEW_QSTR(MP_QSTR_IRQ_FALLING), MP_OBJ_NEW_SMALL_INT(GPIO_FALLING_EDGE) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_IRQ_RISING), MP_OBJ_NEW_SMALL_INT(GPIO_RISING_EDGE) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_IRQ_RISING_FALLING), MP_OBJ_NEW_SMALL_INT(GPIO_BOTH_EDGES) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_IRQ_LOW_LEVEL), MP_OBJ_NEW_SMALL_INT(GPIO_LOW_LEVEL) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_IRQ_HIGH_LEVEL), MP_OBJ_NEW_SMALL_INT(GPIO_HIGH_LEVEL) },
+};
+
+STATIC MP_DEFINE_CONST_DICT(extint_locals_dict, extint_locals_dict_table);
+
+STATIC void ExecuteIntCallback (extint_obj_t *self) {
+ if (self->callback != mp_const_none) {
+ // disable interrupts to avoid nesting
+ uint primsk = disable_irq();
+ // when executing code within a handler we must lock the GC to prevent
+ // any memory allocations. We must also catch any exceptions.
+ gc_lock();
+ nlr_buf_t nlr;
+ if (nlr_push(&nlr) == 0) {
+ mp_call_function_1(self->callback, self);
+ nlr_pop();
+ } else {
+ // uncaught exception; disable the callback so it doesn't run again
+ self->callback = mp_const_none;
+ extint_disable(self);
+ // printing an exception here will cause a stack overflow that ends up in a
+ // hard fault so, is better to signal the uncaught (probably non-recoverable)
+ // exception by blinkg the BLD
+ // TODO: Blink the BLD
+ }
+ gc_unlock();
+ enable_irq(primsk);
+ }
+}
+
+STATIC void GPIOA0IntHandler (void) {
+ EXTI_Handler(GPIOA0_BASE);
+}
+
+STATIC void GPIOA1IntHandler (void) {
+ EXTI_Handler(GPIOA1_BASE);
+}
+
+STATIC void GPIOA2IntHandler (void) {
+ EXTI_Handler(GPIOA2_BASE);
+}
+
+STATIC void GPIOA3IntHandler (void) {
+ EXTI_Handler(GPIOA3_BASE);
+}
+
+// common interrupt handler
+STATIC void EXTI_Handler(uint port) {
+ extint_obj_t *self;
+ uint32_t bit = MAP_GPIOIntStatus(port, true);
+
+ MAP_GPIOIntClear(port, bit);
+ if (NULL != (self = extint_find(port, bit))) {
+ ExecuteIntCallback(self);
+ }
+}
+
+const mp_obj_type_t extint_type = {
+ { &mp_type_type },
+ .name = MP_QSTR_ExtInt,
+ .print = extint_obj_print,
+ .make_new = extint_make_new,
+ .locals_dict = (mp_obj_t)&extint_locals_dict,
+};
+
+void extint_init0(void) {
+ mp_obj_list_init(&MP_STATE_PORT(pyb_extint_list), 0);
+}
+
+extint_obj_t* extint_register(mp_obj_t pin_obj, uint32_t intmode, uint32_t pull, mp_obj_t callback) {
+ const gpio_obj_t *gpio = NULL;
+ extint_obj_t* self;
+ void *handler;
+ uint32_t intnum;
+
+ gpio = gpio_find(pin_obj);
+
+ if (intmode != GPIO_FALLING_EDGE &&
+ intmode != GPIO_RISING_EDGE &&
+ intmode != GPIO_BOTH_EDGES &&
+ intmode != GPIO_LOW_LEVEL &&
+ intmode != GPIO_HIGH_LEVEL) {
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_value_invalid_arguments));
+ }
+ if (pull != PIN_TYPE_STD &&
+ pull != PIN_TYPE_STD_PU &&
+ pull != PIN_TYPE_STD_PD &&
+ pull != PIN_TYPE_OD &&
+ pull != PIN_TYPE_OD_PU &&
+ pull != PIN_TYPE_OD_PD) {
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_value_invalid_arguments));
+ }
+
+ if (NULL == (self = extint_find(gpio->port, gpio->bit))) {
+ self = extint_add(gpio->pin_num, gpio->port, gpio->bit);
+ }
+ else {
+ // we need to update the callback atomically, so we disable the line
+ // before we update anything.
+ extint_disable(self);
+ }
+
+ // invalidate the callback
+ self->callback = NULL;
+
+ // before enabling the interrupt, configure the gpio pin
+ gpio_config(gpio, PIN_MODE_0, GPIO_DIR_MODE_IN, pull, PIN_STRENGTH_4MA);
+
+ MAP_GPIOIntTypeSet(gpio->port, gpio->bit, intmode);
+ switch (gpio->port) {
+ case GPIOA0_BASE:
+ handler = GPIOA0IntHandler;
+ intnum = INT_GPIOA0;
+ break;
+ case GPIOA1_BASE:
+ handler = GPIOA1IntHandler;
+ intnum = INT_GPIOA1;
+ break;
+ case GPIOA2_BASE:
+ handler = GPIOA2IntHandler;
+ intnum = INT_GPIOA2;
+ break;
+ case GPIOA3_BASE:
+ default:
+ handler = GPIOA3IntHandler;
+ intnum = INT_GPIOA3;
+ break;
+ }
+
+ MAP_GPIOIntRegister(gpio->port, handler);
+ // set the interrupt to the lowest priority, to make sure that no ther
+ // isr will be preemted by this one
+ MAP_IntPrioritySet(intnum, INT_PRIORITY_LVL_7);
+
+ // set the new callback
+ self->callback = callback;
+ // enable the interrupt just before leaving
+ extint_enable(self);
+
+ return self;
+}
+
+void extint_enable(extint_obj_t *self) {
+ MAP_GPIOIntClear(self->port, self->bit);
+ MAP_GPIOIntEnable(self->port, self->bit);
+}
+
+void extint_disable(extint_obj_t *self) {
+ MAP_GPIOIntDisable(self->port, self->bit);
+}
+
+void extint_swint(extint_obj_t *self) {
+ ExecuteIntCallback(self);
+}
diff --git a/cc3200/mods/pybextint.h b/cc3200/mods/pybextint.h
new file mode 100644
index 000000000..b479403b2
--- /dev/null
+++ b/cc3200/mods/pybextint.h
@@ -0,0 +1,47 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2013, 2014 Damien P. George
+ * Copyright (c) 2015 Daniel Campora
+ *
+ * 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 PYBEXTINT_H_
+#define PYBEXTINT_H_
+
+typedef struct {
+ mp_obj_base_t base;
+ mp_obj_t callback;
+ uint32_t port;
+ uint8_t pin_num;
+ uint8_t bit;
+} extint_obj_t;
+
+extern const mp_obj_type_t extint_type;
+
+void extint_init0(void);
+extint_obj_t* extint_register(mp_obj_t pin_obj, uint32_t intmode, uint32_t pull, mp_obj_t callback);
+void extint_enable(extint_obj_t *self);
+void extint_disable(extint_obj_t *self);
+void extint_swint(extint_obj_t *self);
+
+#endif /* PYBEXTINT_H_ */
diff --git a/cc3200/mods/pybgpio.c b/cc3200/mods/pybgpio.c
new file mode 100644
index 000000000..cf52b501d
--- /dev/null
+++ b/cc3200/mods/pybgpio.c
@@ -0,0 +1,529 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2013, 2014 Damien P. George
+ * Copyright (c) 2015 Daniel Campora
+ *
+ * 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/mpstate.h"
+#include "mpconfig.h"
+#include MICROPY_HAL_H
+#include "nlr.h"
+#include "misc.h"
+#include "qstr.h"
+#include "obj.h"
+#include "runtime.h"
+#include "inc/hw_types.h"
+#include "inc/hw_gpio.h"
+#include "inc/hw_ints.h"
+#include "inc/hw_memmap.h"
+#include "rom_map.h"
+#include "pin.h"
+#include "prcm.h"
+#include "gpio.h"
+#include "pybgpio.h"
+#include "mpexception.h"
+
+
+/// \moduleref pyb
+/// \class GPIO - control I/O pins
+///
+/// A pin is the basic object to control I/O pins. It has methods to set
+/// the mode of the pin (input or output) and methods to get and set the
+/// digital logic level. For analog control of a pin, see the ADC class.
+///
+/// Usage Model:
+///
+/// All CPU Pins are predefined as pyb.GPIO.cpu.Name
+///
+/// GPIO9_pin = pyb.GPIO.cpu.GPIO9
+///
+/// g = pyb.GPIO(pyb.GPIO.cpu.GPIO9, 0, pyb.GPIO.IN)
+///
+/// CPU pins which correspond to the board pins are available
+/// as `pyb.cpu.Name`.
+///
+/// You can also use strings:
+///
+/// g = pyb.GPIO('GPIO9', 0)
+///
+/// Users can add their own names:
+///
+/// MyMapperDict = { 'LeftMotorDir' : pyb.GPIO.cpu.GPIO11 }
+/// pyb.GPIO.dict(MyMapperDict)
+/// g = pyb.GPIO("LeftMotorDir", 0)
+///
+/// and can query mappings
+///
+/// g = pyb.GPIO("LeftMotorDir")
+///
+/// Users can also add their own mapping function:
+///
+/// def MyMapper(gpio_name):
+/// if gpio_name == "LeftMotorDir":
+/// return pyb.GPIO.cpu.GPIO11
+///
+/// pyb.GPIO.mapper(MyMapper)
+///
+/// So, if you were to call: `pyb.GPIO("LeftMotorDir", pyb.GPIO.OUT)`
+/// then `"LeftMotorDir"` is passed directly to the mapper function.
+///
+/// To summarise, the following order determines how things get mapped into
+/// an ordinal pin number:
+///
+/// 1. Directly specify a GPIO object
+/// 2. User supplied mapping function
+/// 3. User supplied mapping (object must be usable as a dictionary key)
+/// 4. Supply a string which matches a CPU port/pin
+
+void gpio_init0(void) {
+ MP_STATE_PORT(gpio_class_mapper) = mp_const_none;
+ MP_STATE_PORT(gpio_class_map_dict) = mp_const_none;
+}
+
+// C API used to convert a user-supplied pin name into an ordinal pin number.
+const gpio_obj_t *gpio_find(mp_obj_t user_obj) {
+ const gpio_obj_t *gpio_obj;
+
+ // If a pin was provided, then use it
+ if (MP_OBJ_IS_TYPE(user_obj, &gpio_type)) {
+ gpio_obj = user_obj;
+ return gpio_obj;
+ }
+
+ if (MP_STATE_PORT(gpio_class_mapper) != mp_const_none) {
+ gpio_obj = mp_call_function_1(MP_STATE_PORT(gpio_class_mapper), user_obj);
+ if (gpio_obj != mp_const_none) {
+ if (!MP_OBJ_IS_TYPE(gpio_obj, &gpio_type)) {
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable));
+ }
+ return gpio_obj;
+ }
+ // The pin mapping function returned mp_const_none, fall through to
+ // other lookup methods.
+ }
+
+ if (MP_STATE_PORT(gpio_class_map_dict) != mp_const_none) {
+ mp_map_t *gpio_map_map = mp_obj_dict_get_map(MP_STATE_PORT(gpio_class_map_dict));
+ mp_map_elem_t *elem = mp_map_lookup(gpio_map_map, user_obj, MP_MAP_LOOKUP);
+ if (elem != NULL && elem->value != NULL) {
+ gpio_obj = elem->value;
+ return gpio_obj;
+ }
+ }
+
+ // See if the pin name matches a cpu pin
+ gpio_obj = gpio_find_named_pin(&gpio_cpu_pins_locals_dict, user_obj);
+ if (gpio_obj) {
+ return gpio_obj;
+ }
+
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
+}
+
+void gpio_config(const gpio_obj_t *self, uint af, uint mode, uint type, uint strength) {
+ // PIN_MODE_0 means it stays as a GPIO, else, another peripheral will take control of it
+ if (af == PIN_MODE_0) {
+ // enable the peripheral clock for the GPIO port of this pin
+ switch (self->port) {
+ case PORT_A0:
+ MAP_PRCMPeripheralClkEnable(PRCM_GPIOA0, PRCM_RUN_MODE_CLK | PRCM_SLP_MODE_CLK);
+ break;
+ case PORT_A1:
+ MAP_PRCMPeripheralClkEnable(PRCM_GPIOA1, PRCM_RUN_MODE_CLK | PRCM_SLP_MODE_CLK);
+ break;
+ case PORT_A2:
+ MAP_PRCMPeripheralClkEnable(PRCM_GPIOA2, PRCM_RUN_MODE_CLK | PRCM_SLP_MODE_CLK);
+ break;
+ case PORT_A3:
+ MAP_PRCMPeripheralClkEnable(PRCM_GPIOA3, PRCM_RUN_MODE_CLK | PRCM_SLP_MODE_CLK);
+ break;
+ default:
+ break;
+ }
+ // configure the direction
+ MAP_GPIODirModeSet(self->port, self->bit, mode);
+ }
+
+ // now set the alternate function, strenght and type
+ MAP_PinModeSet (self->pin_num, af);
+ MAP_PinConfigSet(self->pin_num, strength, type);
+}
+
+/// \method print()
+/// Return a string describing the pin object.
+STATIC void gpio_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
+ gpio_obj_t *self = self_in;
+ uint32_t af = MAP_PinModeGet(self->pin_num);
+ uint32_t type = gpio_get_type(self);
+ uint32_t strength = gpio_get_strenght(self);
+
+ // pin name
+ print(env, "GPIO(GPIO.cpu.%s, af=%u", qstr_str(self->name), af);
+
+ if (af == PIN_MODE_0) {
+ // IO mode
+ qstr mode_qst;
+ uint32_t mode = gpio_get_mode(self);
+ if (mode == GPIO_DIR_MODE_IN) {
+ mode_qst = MP_QSTR_IN;
+ } else {
+ mode_qst = MP_QSTR_OUT;
+ }
+ print(env, ", mode=GPIO.%s", qstr_str(mode_qst)); // safe because mode_qst has no formatting chars
+ }
+
+ // pin type
+ qstr type_qst;
+ if (type == PIN_TYPE_STD) {
+ type_qst = MP_QSTR_STD;
+ } else if (type == PIN_TYPE_STD_PU) {
+ type_qst = MP_QSTR_STD_PU;
+ } else if (type == PIN_TYPE_STD_PD) {
+ type_qst = MP_QSTR_STD_PD;
+ } else if (type == PIN_TYPE_OD) {
+ type_qst = MP_QSTR_OD;
+ } else if (type == PIN_TYPE_OD_PU) {
+ type_qst = MP_QSTR_OD_PU;
+ } else {
+ type_qst = MP_QSTR_OD_PD;
+ }
+ print(env, ", pull=GPIO.%s", qstr_str(type_qst));
+
+ // Strength
+ qstr str_qst;
+ if (strength == PIN_STRENGTH_2MA) {
+ str_qst = MP_QSTR_S2MA;
+ } else if (strength == PIN_STRENGTH_4MA) {
+ str_qst = MP_QSTR_S4MA;
+ } else {
+ str_qst = MP_QSTR_S6MA;
+ }
+ print(env, ", strength=GPIO.%s)", qstr_str(str_qst));
+}
+
+STATIC mp_obj_t gpio_obj_init_helper(const gpio_obj_t *pin, mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kw_args);
+
+/// \classmethod \constructor(id, ...)
+/// Create a new GPIO object associated with the id. If additional arguments are given,
+/// they are used to initialise the pin. See `init`.
+STATIC mp_obj_t gpio_make_new(mp_obj_t self_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
+ mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true);
+
+ // Run an argument through the mapper and return the result.
+ const gpio_obj_t *pin = gpio_find(args[0]);
+
+ if (n_args > 1) {
+ // pin af given, so configure it
+ mp_map_t kw_args;
+ mp_map_init_fixed_table(&kw_args, n_kw, args + n_args);
+ gpio_obj_init_helper(pin, n_args - 1, args + 1, &kw_args);
+ }
+
+ return (mp_obj_t)pin;
+}
+
+/// \classmethod mapper([fun])
+/// Get or set the pin mapper function.
+STATIC mp_obj_t gpio_mapper(mp_uint_t n_args, const mp_obj_t *args) {
+ if (n_args > 1) {
+ MP_STATE_PORT(gpio_class_mapper) = args[1];
+ return mp_const_none;
+ }
+ return MP_STATE_PORT(gpio_class_mapper);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(gpio_mapper_fun_obj, 1, 2, gpio_mapper);
+STATIC MP_DEFINE_CONST_CLASSMETHOD_OBJ(gpio_mapper_obj, (mp_obj_t)&gpio_mapper_fun_obj);
+
+/// \classmethod dict([dict])
+/// Get or set the pin mapper dictionary.
+STATIC mp_obj_t gpio_map_dict(mp_uint_t n_args, const mp_obj_t *args) {
+ if (n_args > 1) {
+ MP_STATE_PORT(gpio_class_map_dict) = args[1];
+ return mp_const_none;
+ }
+ return MP_STATE_PORT(gpio_class_map_dict);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(gpio_map_dict_fun_obj, 1, 2, gpio_map_dict);
+STATIC MP_DEFINE_CONST_CLASSMETHOD_OBJ(gpio_map_dict_obj, (mp_obj_t)&gpio_map_dict_fun_obj);
+
+/// \method init(mode, pull=Pin.PULL_NONE, af=-1)
+/// Initialise the pin:
+///
+/// - `af` can be in range 0-15, please check the CC3200 datasheet
+/// for the details on the AFs availables on each pin (af=0, keeps it as a gpio pin).
+/// - `mode` can be one of:
+/// - `Pin.IN` - configure the pin for input;
+/// - `Pin.OUT` - configure the pin for output;
+/// - `type` can be one of:
+/// - `Pin.STD` - standard without pull-up or pull-down;
+/// - `Pin.STD_PU` - standard with pull-up resistor;
+/// - `Pin.STD_PD` - standard with pull-down resistor.
+/// - `Pin.OD` - standard without pull up or pull down;
+/// - `Pin.OD_PU` - open drain with pull-up resistor;
+/// - `Pin.OD_PD` - open drain with pull-down resistor.
+/// - `Pin.ANALOG` - configured in analog (adc) mode
+/// - `strength` can be one of:
+/// - `Pin.2MA` - 2ma drive strength;
+/// - `Pin.4MA` - 4ma drive strength;
+/// - `Pin.6MA` - 6ma drive strength;
+///
+/// Returns: `None`.
+STATIC const mp_arg_t gpio_init_args[] = {
+ { MP_QSTR_af, MP_ARG_REQUIRED | MP_ARG_INT },
+ { MP_QSTR_mode, MP_ARG_INT, {.u_int = GPIO_DIR_MODE_OUT} },
+ { MP_QSTR_type, MP_ARG_INT, {.u_int = PIN_TYPE_STD} },
+ { MP_QSTR_str, MP_ARG_INT, {.u_int = PIN_STRENGTH_4MA} },
+};
+#define gpio_INIT_NUM_ARGS MP_ARRAY_SIZE(gpio_init_args)
+
+STATIC mp_obj_t gpio_obj_init_helper(const gpio_obj_t *self, mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
+ // parse args
+ mp_arg_val_t vals[gpio_INIT_NUM_ARGS];
+ mp_arg_parse_all(n_args, args, kw_args, gpio_INIT_NUM_ARGS, gpio_init_args, vals);
+
+ // get the af
+ uint af = vals[0].u_int;
+ if (af < PIN_MODE_0 || af > PIN_MODE_15) {
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
+ }
+ // get the io mode
+ uint mode = vals[1].u_int;
+ if (mode != GPIO_DIR_MODE_IN && mode != GPIO_DIR_MODE_OUT) {
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
+ }
+ // get the type
+ uint type = vals[2].u_int;
+ if (type != PIN_TYPE_STD && type != PIN_TYPE_STD_PU && type != PIN_TYPE_STD_PD &&
+ type != PIN_TYPE_OD && type != PIN_TYPE_OD_PU && type != PIN_TYPE_OD_PD) {
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
+ }
+ // get the strenght
+ uint strength = vals[3].u_int;
+ if (strength != PIN_STRENGTH_2MA && strength != PIN_STRENGTH_4MA && strength != PIN_STRENGTH_6MA) {
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
+ }
+
+ // configure the pin as requested
+ gpio_config (self, af, mode, type, strength);
+
+ return mp_const_none;
+}
+
+STATIC mp_obj_t gpio_obj_init(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
+ return gpio_obj_init_helper(args[0], n_args - 1, args + 1, kw_args);
+}
+MP_DEFINE_CONST_FUN_OBJ_KW(gpio_init_obj, 1, gpio_obj_init);
+
+/// \method value([value])
+/// Get or set the digital logic level of the pin:
+///
+/// - With no argument, return 0 or 1 depending on the logic level of the pin.
+/// - With `value` given, set the logic level of the pin. `value` can be
+/// anything that converts to a boolean. If it converts to `True`, the pin
+/// is set high, otherwise it is set low.
+STATIC mp_obj_t gpio_value(mp_uint_t n_args, const mp_obj_t *args) {
+ gpio_obj_t *self = args[0];
+ if (n_args == 1) {
+ // get the pin value
+ return MP_OBJ_NEW_SMALL_INT(MAP_GPIOPinRead(self->port, self->bit) ? 1 : 0);
+ } else {
+ // set the pin value
+ if (mp_obj_is_true(args[1])) {
+ MAP_GPIOPinWrite(self->port, self->bit, self->bit);
+ } else {
+ MAP_GPIOPinWrite(self->port, self->bit, 0);
+ }
+ return mp_const_none;
+ }
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(gpio_value_obj, 1, 2, gpio_value);
+
+/// \method low()
+/// Set the pin to a low logic level.
+STATIC mp_obj_t gpio_low(mp_obj_t self_in) {
+ gpio_obj_t *self = self_in;
+ MAP_GPIOPinWrite(self->port, self->bit, 0);
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(gpio_low_obj, gpio_low);
+
+/// \method high()
+/// Set the pin to a high logic level.
+STATIC mp_obj_t gpio_high(mp_obj_t self_in) {
+ gpio_obj_t *self = self_in;
+ MAP_GPIOPinWrite(self->port, self->bit, self->bit);
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(gpio_high_obj, gpio_high);
+
+/// \method toggle()
+/// Toggles the value of the pin
+STATIC mp_obj_t gpio_toggle(mp_obj_t self_in) {
+ gpio_obj_t *self = self_in;
+ MAP_GPIOPinWrite(self->port, self->bit, ~MAP_GPIOPinRead(self->port, self->bit));
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(gpio_toggle_obj, gpio_toggle);
+
+/// \method name()
+/// Get the pin name.
+STATIC mp_obj_t gpio_name(mp_obj_t self_in) {
+ gpio_obj_t *self = self_in;
+ return MP_OBJ_NEW_QSTR(self->name);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(gpio_name_obj, gpio_name);
+
+/// \method name()
+/// Returns the cpu name for this pin.
+STATIC mp_obj_t gpio_cpu_name(mp_obj_t self_in) {
+ gpio_obj_t *self = self_in;
+ mp_obj_t result = mp_obj_new_list(0, NULL);
+ mp_obj_list_append(result, MP_OBJ_NEW_QSTR(self->name));
+
+ mp_map_t *map = mp_obj_dict_get_map((mp_obj_t)&gpio_cpu_pins_locals_dict);
+ mp_map_elem_t *elem = map->table;
+
+ for (mp_uint_t i = 0; i < map->used; i++, elem++) {
+ if (elem->value == self) {
+ mp_obj_list_append(result, elem->key);
+ }
+ }
+ return result;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(gpio_cpu_name_obj, gpio_cpu_name);
+
+/// \method port()
+/// Get the pin port.
+STATIC mp_obj_t gpio_port(mp_obj_t self_in) {
+ gpio_obj_t *self = self_in;
+ return mp_obj_new_int(self->port);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(gpio_port_obj, gpio_port);
+
+/// \method pin()
+/// Get the pin number.
+STATIC mp_obj_t gpio_pin(mp_obj_t self_in) {
+ gpio_obj_t *self = self_in;
+ return MP_OBJ_NEW_SMALL_INT(self->pin_num);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(gpio_pin_obj, gpio_pin);
+
+/// \method mode()
+/// Returns the currently configured mode of the gpio pin. The integer returned
+/// will match one of the allowed constants for the mode argument to the init
+/// function.
+STATIC mp_obj_t gpio_mode(mp_obj_t self_in) {
+ return MP_OBJ_NEW_SMALL_INT(gpio_get_mode(self_in));
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(gpio_mode_obj, gpio_mode);
+
+/// \method type()
+/// Returns the currently configured type of the pin. The integer returned
+/// will match one of the allowed constants for the type argument to the init
+/// function.
+STATIC mp_obj_t gpio_type_get(mp_obj_t self_in) {
+ return MP_OBJ_NEW_SMALL_INT(gpio_get_type(self_in));
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(gpio_type_obj, gpio_type_get);
+
+/// \method strength()
+/// Returns the currently configured drive strength of the pin. The integer returned
+/// will match one of the allowed constants for the strength argument to the init
+/// function.
+STATIC mp_obj_t gpio_strength(mp_obj_t self_in) {
+ return MP_OBJ_NEW_SMALL_INT(gpio_get_strenght(self_in));
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(gpio_strenght_obj, gpio_strength);
+
+/// \method af()
+/// Returns the currently configured alternate function of the gpio pin. The integer returned
+/// will match one of the allowed constants for the af argument to the init function.
+STATIC mp_obj_t gpio_af(mp_obj_t self_in) {
+ gpio_obj_t *self = self_in;
+ return MP_OBJ_NEW_SMALL_INT(MAP_PinModeGet(self->pin_num));
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(gpio_af_obj, gpio_af);
+
+STATIC const mp_map_elem_t gpio_locals_dict_table[] = {
+ // instance methods
+ { MP_OBJ_NEW_QSTR(MP_QSTR_init), (mp_obj_t)&gpio_init_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_value), (mp_obj_t)&gpio_value_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_low), (mp_obj_t)&gpio_low_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_high), (mp_obj_t)&gpio_high_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_toggle), (mp_obj_t)&gpio_toggle_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_name), (mp_obj_t)&gpio_name_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_names), (mp_obj_t)&gpio_cpu_name_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_port), (mp_obj_t)&gpio_port_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_pin), (mp_obj_t)&gpio_pin_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_mode), (mp_obj_t)&gpio_mode_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_type), (mp_obj_t)&gpio_type_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_strength), (mp_obj_t)&gpio_strenght_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_af), (mp_obj_t)&gpio_af_obj },
+
+ // class methods
+ { MP_OBJ_NEW_QSTR(MP_QSTR_mapper), (mp_obj_t)&gpio_mapper_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_dict), (mp_obj_t)&gpio_map_dict_obj },
+
+ // class attributes
+ { MP_OBJ_NEW_QSTR(MP_QSTR_cpu), (mp_obj_t)&gpio_cpu_pins_obj_type },
+
+ // class constants
+ /// \constant IN - set the pin to input mode
+ /// \constant OUT - set the pin to output mode
+ /// \constant STD - set the pin to standard mode without pull-up or pull-down
+ /// \constant STD_PU - set the pin to standard mode with pull-up
+ /// \constant STD_PD - set the pin to standard mode with pull-down
+ /// \constant OD - set the pin to open drain mode without pull-up or pull-down
+ /// \constant OD_PU - set the pin to open drain mode with pull-up
+ /// \constant OD_PD - set the pin to open drain mode with pull-down
+ /// \constant 2MA - set the drive strength to 2ma
+ /// \constant 4MA - set the drive strength to 4ma
+ /// \constant 6MA - set the drive strength to 6ma
+ { MP_OBJ_NEW_QSTR(MP_QSTR_IN), MP_OBJ_NEW_SMALL_INT(GPIO_DIR_MODE_IN) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_OUT), MP_OBJ_NEW_SMALL_INT(GPIO_DIR_MODE_OUT) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_STD), MP_OBJ_NEW_SMALL_INT(PIN_TYPE_STD) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_STD_PU), MP_OBJ_NEW_SMALL_INT(PIN_TYPE_STD_PU) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_STD_PD), MP_OBJ_NEW_SMALL_INT(PIN_TYPE_STD_PD) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_OD), MP_OBJ_NEW_SMALL_INT(PIN_TYPE_OD) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_OD_PU), MP_OBJ_NEW_SMALL_INT(PIN_TYPE_OD_PU) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_OD_PD), MP_OBJ_NEW_SMALL_INT(PIN_TYPE_OD_PD) },
+
+ { MP_OBJ_NEW_QSTR(MP_QSTR_S2MA), MP_OBJ_NEW_SMALL_INT(PIN_STRENGTH_2MA) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_S4MA), MP_OBJ_NEW_SMALL_INT(PIN_STRENGTH_4MA) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_S6MA), MP_OBJ_NEW_SMALL_INT(PIN_STRENGTH_6MA) },
+};
+
+STATIC MP_DEFINE_CONST_DICT(gpio_locals_dict, gpio_locals_dict_table);
+
+const mp_obj_type_t gpio_type = {
+ { &mp_type_type },
+ .name = MP_QSTR_GPIO,
+ .print = gpio_print,
+ .make_new = gpio_make_new,
+ .locals_dict = (mp_obj_t)&gpio_locals_dict,
+};
diff --git a/cc3200/mods/pybgpio.h b/cc3200/mods/pybgpio.h
new file mode 100644
index 000000000..08a495803
--- /dev/null
+++ b/cc3200/mods/pybgpio.h
@@ -0,0 +1,68 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2013, 2014 Damien P. George
+ * Copyright (c) 2015 Daniel Campora
+ *
+ * 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.
+ */
+
+// This file requires pin_defs_xxx.h (which has port specific enums and
+// defines, so we include it here. It should never be included directly
+
+#include MICROPY_PIN_DEFS_PORT_H
+
+typedef struct {
+ mp_obj_base_t base;
+ qstr name;
+ uint32_t port;
+ uint32_t bit : 8;
+ uint32_t pin_num : 7;
+} gpio_obj_t;
+
+extern const mp_obj_type_t gpio_type;
+
+typedef struct {
+ const char *name;
+ const gpio_obj_t *gpio;
+} gpio_named_pin_t;
+
+extern const gpio_named_pin_t gpio_cpu_pins[];
+
+typedef struct {
+ mp_obj_base_t base;
+ qstr name;
+ const gpio_named_pin_t *named_pins;
+} gpio_named_pins_obj_t;
+
+extern const mp_obj_type_t gpio_cpu_pins_obj_type;
+extern const mp_obj_dict_t gpio_cpu_pins_locals_dict;
+
+MP_DECLARE_CONST_FUN_OBJ(gpio_init_obj);
+
+void gpio_init0(void);
+void gpio_config(const gpio_obj_t *self, uint af, uint mode, uint type, uint strength);
+const gpio_obj_t *gpio_find(mp_obj_t user_obj);
+const gpio_obj_t *gpio_find_named_pin(const mp_obj_dict_t *named_pins, mp_obj_t name);
+uint32_t gpio_get_mode(const gpio_obj_t *self);
+uint32_t gpio_get_type(const gpio_obj_t *self);
+uint32_t gpio_get_strenght(const gpio_obj_t *self);
+
diff --git a/cc3200/mods/pybrtc.c b/cc3200/mods/pybrtc.c
new file mode 100644
index 000000000..8d4383068
--- /dev/null
+++ b/cc3200/mods/pybrtc.c
@@ -0,0 +1,158 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2013, 2014 Damien P. George
+ * Copyright (c) 2015 Daniel Campora
+ *
+ * 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 "mpconfig.h"
+#include MICROPY_HAL_H
+#include "misc.h"
+#include "qstr.h"
+#include "obj.h"
+#include "runtime.h"
+#include "modutime.h"
+#include "inc/hw_types.h"
+#include "inc/hw_ints.h"
+#include "inc/hw_memmap.h"
+#include "rom_map.h"
+#include "prcm.h"
+#include "pybrtc.h"
+
+/// \moduleref pyb
+/// \class RTC - real time clock
+///
+/// The RTC is and independent clock that keeps track of the date
+/// and time.
+///
+/// Example usage:
+///
+/// rtc = pyb.RTC()
+/// rtc.datetime((2014, 5, 1, 4, 13, 0, 0, 0))
+/// print(rtc.datetime())
+
+void pybrtc_init(void) {
+ // if RTC was previously set leave it alone
+ if (MAP_PRCMSysResetCauseGet() == PRCM_POWER_ON) {
+ // fresh reset; configure RTC Calendar
+ // set the date to 1st Jan 2015
+ // set the time to 00:00:00
+ uint32_t seconds = mod_time_seconds_since_2000(2015, 1, 1, 0, 0, 0);
+
+ MAP_PRCMRTCSet(seconds, 0);
+
+ // Mark that the RTC is in use
+ MAP_PRCMRTCInUseSet();
+ }
+}
+
+/******************************************************************************/
+// Micro Python bindings
+
+typedef struct _pyb_rtc_obj_t {
+ mp_obj_base_t base;
+} pyb_rtc_obj_t;
+
+STATIC const pyb_rtc_obj_t pyb_rtc_obj = {{&pyb_rtc_type}};
+
+/// \classmethod \constructor()
+/// Create an RTC object.
+STATIC mp_obj_t pyb_rtc_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
+ // check arguments
+ mp_arg_check_num(n_args, n_kw, 0, 0, false);
+
+ // return constant object
+ return (mp_obj_t)&pyb_rtc_obj;
+}
+
+/// \method datetime([datetimetuple])
+/// Get or set the date and time of the RTC.
+///
+/// With no arguments, this method returns an 8-tuple with the current
+/// date and time. With 1 argument (being an 8-tuple) it sets the date
+/// and time.
+///
+/// The 8-tuple has the following format:
+///
+/// (year, month, day, weekday, hours, minutes, seconds, milliseconds)
+///
+/// `weekday` is 1-7 for Monday through Sunday.
+///
+mp_obj_t pyb_rtc_datetime(mp_uint_t n_args, const mp_obj_t *args) {
+ mod_struct_time tm;
+ uint32_t seconds;
+ uint16_t mseconds;
+
+ if (n_args == 1) {
+ // get the seconds and the milliseconds from the RTC
+ MAP_PRCMRTCGet(&seconds, &mseconds);
+ mseconds = RTC_CYCLES_U16MS(mseconds);
+ mod_time_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(mseconds)
+ };
+ return mp_obj_new_tuple(8, tuple);
+ } else {
+ // set date and time
+ mp_obj_t *items;
+ mp_obj_get_array_fixed_n(args[1], 8, &items);
+
+ tm.tm_year = mp_obj_get_int(items[0]);
+ tm.tm_mon = mp_obj_get_int(items[1]);
+ tm.tm_mday = mp_obj_get_int(items[2]);
+ // Skip the weekday
+ tm.tm_hour = mp_obj_get_int(items[4]);
+ tm.tm_min = mp_obj_get_int(items[5]);
+ tm.tm_sec = mp_obj_get_int(items[6]);
+ mseconds = mp_obj_get_int(items[7]);
+
+ seconds = mod_time_seconds_since_2000(tm.tm_year, tm.tm_mon, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec);
+ mseconds = RTC_U16MS_CYCLES(mseconds);
+ MAP_PRCMRTCSet(seconds, mseconds);
+
+ return mp_const_none;
+ }
+}
+MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_rtc_datetime_obj, 1, 2, pyb_rtc_datetime);
+
+STATIC const mp_map_elem_t pyb_rtc_locals_dict_table[] = {
+ { MP_OBJ_NEW_QSTR(MP_QSTR_datetime), (mp_obj_t)&pyb_rtc_datetime_obj },
+};
+STATIC MP_DEFINE_CONST_DICT(pyb_rtc_locals_dict, pyb_rtc_locals_dict_table);
+
+const mp_obj_type_t pyb_rtc_type = {
+ { &mp_type_type },
+ .name = MP_QSTR_RTC,
+ .make_new = pyb_rtc_make_new,
+ .locals_dict = (mp_obj_t)&pyb_rtc_locals_dict,
+};
diff --git a/cc3200/mods/pybrtc.h b/cc3200/mods/pybrtc.h
new file mode 100644
index 000000000..abe38cc38
--- /dev/null
+++ b/cc3200/mods/pybrtc.h
@@ -0,0 +1,33 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2013, 2014 Damien P. George
+ * Copyright (c) 2015 Daniel Campora
+ *
+ * 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.
+ */
+
+#define RTC_U16MS_CYCLES(msec) ((msec * 1024) / 1000)
+#define RTC_CYCLES_U16MS(cycles) ((cycles * 1000) / 1024)
+
+extern const mp_obj_type_t pyb_rtc_type;
+
+void pybrtc_init(void);
diff --git a/cc3200/mods/pybstdio.c b/cc3200/mods/pybstdio.c
new file mode 100644
index 000000000..2d6a1c07b
--- /dev/null
+++ b/cc3200/mods/pybstdio.c
@@ -0,0 +1,174 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2013, 2014 Damien P. George
+ * Copyright (c) 2015 Daniel Campora
+ *
+ * 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 <errno.h>
+
+#include "py/mpstate.h"
+#include "mpconfig.h"
+#include "misc.h"
+#include "qstr.h"
+#include "misc.h"
+#include "obj.h"
+#include "stream.h"
+#include MICROPY_HAL_H
+#include "pybuart.h"
+#include "telnet.h"
+#include "pybstdio.h"
+
+// TODO make stdin, stdout and stderr writable objects so they can
+// be changed by Python code. This requires some changes, as these
+// objects are in a read-only module (py/modsys.c).
+
+void stdout_tx_str(const char *str) {
+ stdout_tx_strn(str, strlen(str));
+}
+
+void stdout_tx_strn(const char *str, mp_uint_t len) {
+ if (MP_STATE_PORT(pyb_stdio_uart) != NULL) {
+ uart_tx_strn(MP_STATE_PORT(pyb_stdio_uart), str, len);
+ }
+ // and also to telnet
+ if (telnet_is_active()) {
+ telnet_tx_strn(str, len);
+ }
+}
+
+void stdout_tx_strn_cooked(const char *str, mp_uint_t len) {
+ // send stdout to UART
+ if (MP_STATE_PORT(pyb_stdio_uart) != NULL) {
+ uart_tx_strn_cooked(MP_STATE_PORT(pyb_stdio_uart), str, len);
+ }
+ // and also to telnet
+ if (telnet_is_active()) {
+ telnet_tx_strn_cooked(str, len);
+ }
+}
+
+int stdin_rx_chr(void) {
+ for ( ;; ) {
+ if (telnet_rx_any()) {
+ return telnet_rx_char();
+ }
+ else if (MP_STATE_PORT(pyb_stdio_uart) != NULL && uart_rx_any(MP_STATE_PORT(pyb_stdio_uart))) {
+ return uart_rx_char(MP_STATE_PORT(pyb_stdio_uart));
+ }
+ HAL_Delay(1);
+ }
+}
+
+/******************************************************************************/
+// Micro Python bindings
+
+#define STDIO_FD_IN (0)
+#define STDIO_FD_OUT (1)
+#define STDIO_FD_ERR (2)
+
+typedef struct _pyb_stdio_obj_t {
+ mp_obj_base_t base;
+ int fd;
+} pyb_stdio_obj_t;
+
+void stdio_obj_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
+ pyb_stdio_obj_t *self = self_in;
+ print(env, "<io.FileIO %d>", self->fd);
+}
+
+STATIC mp_uint_t stdio_read(mp_obj_t self_in, void *buf, mp_uint_t size, int *errcode) {
+ pyb_stdio_obj_t *self = self_in;
+ if (self->fd == STDIO_FD_IN) {
+ for (uint i = 0; i < size; i++) {
+ int c = stdin_rx_chr();
+ if (c == '\r') {
+ c = '\n';
+ }
+ ((byte*)buf)[i] = c;
+ }
+ return size;
+ } else {
+ *errcode = EPERM;
+ return MP_STREAM_ERROR;
+ }
+}
+
+STATIC mp_uint_t stdio_write(mp_obj_t self_in, const void *buf, mp_uint_t size, int *errcode) {
+ pyb_stdio_obj_t *self = self_in;
+ if (self->fd == STDIO_FD_OUT || self->fd == STDIO_FD_ERR) {
+ stdout_tx_strn_cooked(buf, size);
+ return size;
+ } else {
+ *errcode = EPERM;
+ return MP_STREAM_ERROR;
+ }
+}
+
+mp_obj_t stdio_obj___exit__(mp_uint_t n_args, const mp_obj_t *args) {
+ return mp_const_none;
+}
+static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(stdio_obj___exit___obj, 4, 4, stdio_obj___exit__);
+
+// TODO gc hook to close the file if not already closed
+
+STATIC const mp_map_elem_t stdio_locals_dict_table[] = {
+ { MP_OBJ_NEW_QSTR(MP_QSTR_read), (mp_obj_t)&mp_stream_read_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_readall), (mp_obj_t)&mp_stream_readall_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_readline), (mp_obj_t)&mp_stream_unbuffered_readline_obj},
+ { MP_OBJ_NEW_QSTR(MP_QSTR_write), (mp_obj_t)&mp_stream_write_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_close), (mp_obj_t)&mp_identity_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR___del__), (mp_obj_t)&mp_identity_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR___enter__), (mp_obj_t)&mp_identity_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR___exit__), (mp_obj_t)&stdio_obj___exit___obj },
+};
+
+STATIC MP_DEFINE_CONST_DICT(stdio_locals_dict, stdio_locals_dict_table);
+
+STATIC const mp_stream_p_t stdio_obj_stream_p = {
+ .read = stdio_read,
+ .write = stdio_write,
+ .is_text = true,
+};
+
+STATIC const mp_obj_type_t stdio_obj_type = {
+ { &mp_type_type },
+ .name = MP_QSTR_FileIO,
+ // TODO .make_new?
+ .print = stdio_obj_print,
+ .getiter = mp_identity,
+ .iternext = mp_stream_unbuffered_iter,
+ .stream_p = &stdio_obj_stream_p,
+ .locals_dict = (mp_obj_t)&stdio_locals_dict,
+};
+
+/// \moduleref sys
+/// \constant stdin - standard input (connected to UART0, or to telnet, configurable)
+/// \constant stdout - standard output (connected to UART0, and optionally to telnet)
+/// \constant stderr - standard error (connected to UART0, and optionally to telnet)
+const pyb_stdio_obj_t mp_sys_stdin_obj = {{&stdio_obj_type}, .fd = STDIO_FD_IN};
+const pyb_stdio_obj_t mp_sys_stdout_obj = {{&stdio_obj_type}, .fd = STDIO_FD_OUT};
+const pyb_stdio_obj_t mp_sys_stderr_obj = {{&stdio_obj_type}, .fd = STDIO_FD_ERR};
diff --git a/cc3200/mods/pybstdio.h b/cc3200/mods/pybstdio.h
new file mode 100644
index 000000000..f987e8bc4
--- /dev/null
+++ b/cc3200/mods/pybstdio.h
@@ -0,0 +1,31 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2013, 2014 Damien P. George
+ * Copyright (c) 2015 Daniel Campora
+ *
+ * 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.
+ */
+
+void stdout_tx_str(const char *str);
+void stdout_tx_strn(const char *str, mp_uint_t len);
+void stdout_tx_strn_cooked(const char *str, mp_uint_t len);
+int stdin_rx_chr(void);
diff --git a/cc3200/mods/pybsystick.c b/cc3200/mods/pybsystick.c
new file mode 100644
index 000000000..e934ab7dd
--- /dev/null
+++ b/cc3200/mods/pybsystick.c
@@ -0,0 +1,93 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2013, 2014 Damien P. George
+ * Copyright (c) 2015 Daniel Campora
+ *
+ * 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 "mpconfig.h"
+#include MICROPY_HAL_H
+#include "misc.h"
+#include "nlr.h"
+#include "qstr.h"
+#include "obj.h"
+#include "irq.h"
+#include "pybsystick.h"
+#include "systick.h"
+#include "inc/hw_types.h"
+#include "inc/hw_nvic.h"
+
+#ifdef USE_FREERTOS
+#include "FreeRTOS.h"
+#include "task.h"
+#endif
+
+
+bool sys_tick_has_passed(uint32_t start_tick, uint32_t delay_ms) {
+ return HAL_GetTick() - start_tick >= delay_ms;
+}
+
+// waits until at least delay_ms milliseconds have passed from the sampling of
+// startTick. Handles overflow properly. Assumes stc was taken from
+// HAL_GetTick() some time before calling this function.
+void sys_tick_wait_at_least(uint32_t start_tick, uint32_t delay_ms) {
+#ifdef USE_FREERTOS
+ vTaskDelay (delay_ms / portTICK_PERIOD_MS);
+#else
+ while (!sys_tick_has_passed(start_tick, delay_ms)) {
+ __WFI(); // enter sleep mode, waiting for interrupt
+ }
+#endif
+}
+
+// The SysTick timer counts down at HAL_FCPU_HZ, so we can use that knowledge
+// to grab a microsecond counter.
+//
+// We assume that HAL_GetTick returns milliseconds.
+uint32_t sys_tick_get_microseconds(void) {
+ mp_uint_t irq_state = disable_irq();
+ uint32_t counter = SysTickValueGet();
+ uint32_t milliseconds = HAL_GetTick();
+ uint32_t status = (HWREG(NVIC_ST_CTRL));
+ enable_irq(irq_state);
+
+ // It's still possible for the countflag bit to get set if the counter was
+ // reloaded between reading VAL and reading CTRL. With interrupts disabled
+ // it definitely takes less than 50 HCLK cycles between reading VAL and
+ // reading CTRL, so the test (counter > 50) is to cover the case where VAL
+ // is +ve and very close to zero, and the COUNTFLAG bit is also set.
+ if ((status & NVIC_ST_CTRL_COUNT) && counter > 50) {
+ // This means that the HW reloaded VAL between the time we read VAL and the
+ // time we read CTRL, which implies that there is an interrupt pending
+ // to increment the tick counter.
+ milliseconds++;
+ }
+ uint32_t load = (HWREG(NVIC_ST_RELOAD));
+ counter = load - counter; // Convert from decrementing to incrementing
+
+ // ((load + 1) / 1000) is the number of counts per microsecond.
+ //
+ // counter / ((load + 1) / 1000) scales from the systick clock to microseconds
+ // and is the same thing as (counter * 1000) / (load + 1)
+ return milliseconds * 1000 + (counter * 1000) / (load + 1);
+}
diff --git a/cc3200/mods/pybsystick.h b/cc3200/mods/pybsystick.h
new file mode 100644
index 000000000..abc61939b
--- /dev/null
+++ b/cc3200/mods/pybsystick.h
@@ -0,0 +1,30 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2013, 2014 Damien P. George
+ * Copyright (c) 2015 Daniel Campora
+ *
+ * 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.
+ */
+
+void sys_tick_wait_at_least(uint32_t stc, uint32_t delay_ms);
+bool sys_tick_has_passed(uint32_t stc, uint32_t delay_ms);
+uint32_t sys_tick_get_microseconds(void);
diff --git a/cc3200/mods/pybuart.c b/cc3200/mods/pybuart.c
new file mode 100644
index 000000000..8fad7eaa4
--- /dev/null
+++ b/cc3200/mods/pybuart.c
@@ -0,0 +1,682 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2013, 2014 Damien P. George
+ * Copyright (c) 2015 Daniel Campora
+ *
+ * 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 <stdarg.h>
+#include <errno.h>
+#include <stdint.h>
+
+#include "py/mpstate.h"
+#include "mpconfig.h"
+#include MICROPY_HAL_H
+#include "nlr.h"
+#include "misc.h"
+#include "qstr.h"
+#include "obj.h"
+#include "runtime.h"
+#include "stream.h"
+#include "inc/hw_types.h"
+#include "inc/hw_gpio.h"
+#include "inc/hw_ints.h"
+#include "inc/hw_memmap.h"
+#include "inc/hw_uart.h"
+#include "rom_map.h"
+#include "interrupt.h"
+#include "prcm.h"
+#include "gpio.h"
+#include "uart.h"
+#include "pin.h"
+#include "pybuart.h"
+#include "pybgpio.h"
+#include "pybioctl.h"
+#include "pybstdio.h"
+#include "mpexception.h"
+#include "osi.h"
+
+
+/// \moduleref pyb
+/// \class UART - duplex serial communication bus
+///
+/// UART implements the standard UART/USART duplex serial communications protocol. At
+/// the physical level it consists of 2 lines: RX and TX.
+///
+/// UART objects can be created and initialised using:
+///
+/// from pyb import UART
+///
+/// uart = UART(1, 9600) # init with given baudrate
+/// uart.init(9600, bits=8, stop=1, parity=None) # init with given parameters
+///
+/// Bits can be 5, 6, 7, 8, parity can be None, 0 (even), 1 (odd). Stop can be 1 or 2.
+///
+/// A UART object acts like a stream object and reading and writing is done
+/// using the standard stream methods:
+///
+/// uart.read(10) # read 10 characters, returns a bytes object
+/// uart.readall() # read all available characters
+/// uart.readline() # read a line
+/// uart.readinto(buf) # read and store into the given buffer
+/// uart.write('abc') # write the 3 characters
+///
+/// Individual characters can be read/written using:
+///
+/// uart.readchar() # read 1 character and returns it as an integer
+/// uart.writechar(42) # write 1 character
+///
+/// To check if there is anything to be read, use:
+///
+/// uart.any() # returns True if any characters waiting
+
+
+
+/******************************************************************************
+ DECLARE PRIVATE FUNCTIONS
+ ******************************************************************************/
+STATIC void UARTGenericIntHandler(uint32_t uart_id);
+STATIC void UART0IntHandler(void);
+STATIC void UART1IntHandler(void);
+STATIC mp_obj_t pyb_uart_deinit(mp_obj_t self_in);
+
+/******************************************************************************
+ DEFINE PRIVATE TYPES
+ ******************************************************************************/
+
+struct _pyb_uart_obj_t {
+ mp_obj_base_t base;
+ pyb_uart_t uart_id;
+ uint reg;
+ uint baudrate;
+ uint config;
+ uint flowcontrol;
+ byte *read_buf; // read buffer pointer
+ uint16_t timeout; // timeout waiting for first char
+ uint16_t timeout_char; // timeout waiting between chars
+ uint16_t read_buf_len; // len in chars; buf can hold len-1 chars
+ volatile uint16_t read_buf_head; // indexes first empty slot
+ uint16_t read_buf_tail; // indexes first full slot (not full if equals head)
+ bool enabled;
+};
+
+#define PYBUART_TX_WAIT_MS 1
+#define PYBUART_TX_MAX_TIMEOUT_MS 5
+
+/******************************************************************************
+ DEFINE PUBLIC FUNCTIONS
+ ******************************************************************************/
+void uart_init0 (void) {
+ for (int i = 0; i < MP_ARRAY_SIZE(MP_STATE_PORT(pyb_uart_obj_all)); i++) {
+ MP_STATE_PORT(pyb_uart_obj_all)[i] = NULL;
+ }
+}
+
+// unregister all interrupt sources
+void uart_deinit(void) {
+ for (int i = 0; i < MP_ARRAY_SIZE(MP_STATE_PORT(pyb_uart_obj_all)); i++) {
+ pyb_uart_obj_t *self = MP_STATE_PORT(pyb_uart_obj_all)[i];
+ if (self != NULL) {
+ pyb_uart_deinit(self);
+ }
+ }
+}
+
+// assumes Init parameters have been set up correctly
+bool uart_init2(pyb_uart_obj_t *self) {
+ uint uartPerh;
+
+ switch (self->uart_id) {
+ case PYB_UART_1:
+ self->reg = UARTA0_BASE;
+ uartPerh = PRCM_UARTA0;
+ MAP_PinTypeUART(PIN_55, PIN_MODE_3);
+ MAP_PinTypeUART(PIN_57, PIN_MODE_3);
+ MAP_UARTIntRegister(UARTA0_BASE, UART0IntHandler);
+ MAP_IntPrioritySet(INT_UARTA0, INT_PRIORITY_LVL_7);
+ break;
+ case PYB_UART_2:
+ self->reg = UARTA1_BASE;
+ uartPerh = PRCM_UARTA1;
+ MAP_PinTypeUART(PIN_58, PIN_MODE_6);
+ MAP_PinTypeUART(PIN_59, PIN_MODE_6);
+ MAP_UARTIntRegister(UARTA1_BASE, UART1IntHandler);
+ MAP_IntPrioritySet(INT_UARTA1, INT_PRIORITY_LVL_7);
+ break;
+ default:
+ return false;
+ }
+
+ // Enable the peripheral clock
+ MAP_PRCMPeripheralClkEnable(uartPerh, PRCM_RUN_MODE_CLK | PRCM_SLP_MODE_CLK);
+
+ // Reset the uart
+ MAP_PRCMPeripheralReset(uartPerh);
+
+ // Initialize the UART
+ MAP_UARTConfigSetExpClk(self->reg, MAP_PRCMPeripheralClockGet(uartPerh),
+ self->baudrate, self->config);
+
+ // Enbale the FIFO
+ MAP_UARTFIFOEnable(self->reg);
+
+ // Configure the FIFO interrupt levels
+ MAP_UARTFIFOLevelSet(self->reg, UART_FIFO_TX4_8, UART_FIFO_RX4_8);
+
+ // Configure the flow control mode
+ UARTFlowControlSet(self->reg, self->flowcontrol);
+
+ // Enable the RX and RX timeout interrupts
+ MAP_UARTIntEnable(self->reg, UART_INT_RX | UART_INT_RT);
+
+ self->enabled = true;
+
+ return true;
+}
+
+bool uart_init(pyb_uart_obj_t *self, uint baudrate) {
+ self->baudrate = baudrate;
+ self->config = UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE;
+ self->flowcontrol = UART_FLOWCONTROL_NONE;
+ return uart_init2(self);
+}
+
+bool uart_rx_any(pyb_uart_obj_t *self) {
+ return (self->read_buf_tail != self->read_buf_head || MAP_UARTCharsAvail(self->reg));
+}
+
+// Waits at most timeout milliseconds for at least 1 char to become ready for
+// reading (from buf or for direct reading).
+// Returns true if something available, false if not.
+STATIC bool uart_rx_wait(pyb_uart_obj_t *self, uint32_t timeout) {
+ for (;;) {
+ if (uart_rx_any(self)) {
+ return true; // have at least 1 char ready for reading
+ }
+ if (timeout > 0) {
+ HAL_Delay (1);
+ timeout--;
+ }
+ else {
+ return false;
+ }
+ }
+}
+
+int uart_rx_char(pyb_uart_obj_t *self) {
+ if (self->read_buf_tail != self->read_buf_head) {
+ // buffering via IRQ
+ int data = self->read_buf[self->read_buf_tail];
+ self->read_buf_tail = (self->read_buf_tail + 1) % self->read_buf_len;
+ return data;
+ } else {
+ // no buffering
+ return MAP_UARTCharGetNonBlocking(self->reg);
+ }
+}
+
+bool uart_tx_char(pyb_uart_obj_t *self, int c) {
+ uint32_t timeout = 0;
+
+ while (!MAP_UARTCharPutNonBlocking(self->reg, c)) {
+ if (timeout++ > (PYBUART_TX_MAX_TIMEOUT_MS / PYBUART_TX_WAIT_MS)) {
+ return false;
+ }
+ HAL_Delay (PYBUART_TX_WAIT_MS);
+ }
+ return true;
+}
+
+bool uart_tx_strn(pyb_uart_obj_t *self, const char *str, uint len) {
+ for (const char *top = str + len; str < top; str++) {
+ if (!uart_tx_char(self, *str)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+void uart_tx_strn_cooked(pyb_uart_obj_t *self, const char *str, uint len) {
+ for (const char *top = str + len; str < top; str++) {
+ if (*str == '\n') {
+ uart_tx_char(self, '\r');
+ }
+ uart_tx_char(self, *str);
+ }
+}
+
+/******************************************************************************
+ DEFINE PRIVATE FUNCTIONS
+ ******************************************************************************/
+
+STATIC void UARTGenericIntHandler(uint32_t uart_id) {
+ pyb_uart_obj_t *self = MP_STATE_PORT(pyb_uart_obj_all)[uart_id];
+ uint32_t status;
+
+ if (self == NULL) {
+ // UART object has not been set, so we can't do anything, not
+ // even disable the IRQ. This should never happen.
+ return;
+ }
+
+ status = MAP_UARTIntStatus(self->reg, true);
+
+ // Receive interrupt
+ if (status & (UART_INT_RX | UART_INT_RT)) {
+ MAP_UARTIntClear(self->reg, UART_INT_RX | UART_INT_RT);
+ while (UARTCharsAvail(self->reg)) {
+ int data = MAP_UARTCharGetNonBlocking(self->reg);
+ if (MICROPY_STDIO_UART == self->uart_id && data == user_interrupt_char) {
+ // raise exception when interrupts are finished
+ mpexception_keyboard_nlr_jump();
+ }
+ else if (self->read_buf_len != 0) {
+ uint16_t next_head = (self->read_buf_head + 1) % self->read_buf_len;
+ if (next_head != self->read_buf_tail) {
+ // only store data if room in buf
+ self->read_buf[self->read_buf_head] = data;
+ self->read_buf_head = next_head;
+ }
+ }
+ }
+ }
+}
+
+STATIC void UART0IntHandler(void) {
+ UARTGenericIntHandler(0);
+}
+
+STATIC void UART1IntHandler(void) {
+ UARTGenericIntHandler(1);
+}
+
+/******************************************************************************/
+/* Micro Python bindings */
+
+STATIC void pyb_uart_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
+ pyb_uart_obj_t *self = self_in;
+ if (!self->enabled) {
+ print(env, "UART(%u)", self->uart_id);
+ } else {
+ print(env, "UART(%u, baudrate=%u, bits=", self->uart_id, self->baudrate);
+ switch (self->config & UART_CONFIG_WLEN_MASK) {
+ case UART_CONFIG_WLEN_5:
+ print(env, "5");
+ break;
+ case UART_CONFIG_WLEN_6:
+ print(env, "6");
+ break;
+ case UART_CONFIG_WLEN_7:
+ print(env, "7");
+ break;
+ case UART_CONFIG_WLEN_8:
+ print(env, "8");
+ break;
+ default:
+ break;
+ }
+ if ((self->config & UART_CONFIG_PAR_MASK) == UART_CONFIG_PAR_NONE) {
+ print(env, ", parity=None");
+ } else {
+ print(env, ", parity=%u", (self->config & UART_CONFIG_PAR_MASK) == UART_CONFIG_PAR_EVEN ? 0 : 1);
+ }
+ print(env, ", stop=%u, timeout=%u, timeout_char=%u, read_buf_len=%u)",
+ (self->config & UART_CONFIG_STOP_MASK) == UART_CONFIG_STOP_ONE ? 1 : 2,
+ self->timeout, self->timeout_char, self->read_buf_len);
+ }
+}
+
+/// \method init(baudrate, bits=8, parity=None, stop=1, *, timeout=1000, timeout_char=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.
+/// - `flowcontrol` is the flow control mode, `None`, `UART.FLOW_TX`,
+/// `UART.FLOW_RX', 'UART.FLOW_TXRX`.
+/// - `timeout` is the timeout in milliseconds to wait for the first character.
+/// - `timeout_char` is the timeout in milliseconds to wait between characters.
+/// - `read_buf_len` is the character length of the read buffer (0 to disable).
+STATIC const mp_arg_t pyb_uart_init_args[] = {
+ { MP_QSTR_baudrate, MP_ARG_REQUIRED | MP_ARG_INT, },
+ { MP_QSTR_bits, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 8} },
+ { MP_QSTR_parity, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
+ { MP_QSTR_stop, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1} },
+ { MP_QSTR_flow, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_int = UART_FLOWCONTROL_NONE} },
+ { 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 = 1} },
+ { MP_QSTR_read_buf_len, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 64} },
+};
+
+STATIC mp_obj_t pyb_uart_init_helper(pyb_uart_obj_t *self, mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+ bool success;
+
+ // parse args
+ mp_arg_val_t args[MP_ARRAY_SIZE(pyb_uart_init_args)];
+ mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(pyb_uart_init_args), pyb_uart_init_args, args);
+
+ // set the UART configuration values
+ if (n_args > 1) {
+ self->baudrate = args[0].u_int;
+ switch (args[1].u_int) {
+ case 5:
+ self->config = UART_CONFIG_WLEN_5;
+ break;
+ case 6:
+ self->config = UART_CONFIG_WLEN_6;
+ break;
+ case 7:
+ self->config = UART_CONFIG_WLEN_7;
+ break;
+ case 8:
+ self->config = UART_CONFIG_WLEN_8;
+ break;
+ default:
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
+ break;
+ }
+ // Parity
+ if (args[2].u_obj == mp_const_none) {
+ self->config |= UART_CONFIG_PAR_NONE;
+ } else {
+ self->config |= ((mp_obj_get_int(args[2].u_obj) & 1) ? UART_CONFIG_PAR_ODD : UART_CONFIG_PAR_EVEN);
+ }
+ // Stop bits
+ self->config |= (args[3].u_int == 1 ? UART_CONFIG_STOP_ONE : UART_CONFIG_STOP_TWO);
+
+ // Flow control
+ self->flowcontrol = args[4].u_int;
+ success = uart_init2(self);
+ } else {
+ success = uart_init(self, args[0].u_int);
+ }
+
+ // init UART (if it fails, something weird happened)
+ if (!success) {
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_operation_failed));
+ }
+
+ // set timeouts
+ self->timeout = args[5].u_int;
+ self->timeout_char = args[6].u_int;
+
+ // setup the read buffer
+ m_del(byte, self->read_buf, self->read_buf_len);
+ self->read_buf_head = 0;
+ self->read_buf_tail = 0;
+
+ if (args[7].u_int <= 0) {
+ // no read buffer
+ self->read_buf_len = 0;
+ self->read_buf = NULL;
+ MAP_UARTIntDisable(self->reg, UART_INT_RX | UART_INT_RT);
+ } else {
+ // read buffer using interrupts
+ self->read_buf_len = args[7].u_int;
+ self->read_buf = m_new(byte, args[7].u_int);
+ }
+
+ return mp_const_none;
+}
+
+/// \classmethod \constructor(bus, ...)
+///
+/// Construct a UART object on the given bus. `bus` can be 1-2
+/// With no additional parameters, the UART object is created but not
+/// initialised (it has the settings from the last initialisation of
+/// the bus, if any).
+/// When only the baud rate is given the UART object is created and
+/// initialized with the default configuration of: 8 bit transfers,
+/// 1 stop bit, no parity and flow control disabled.
+/// See `init` for parameters of initialisation.
+/// If extra arguments are given, the bus is initialised with these arguments
+/// See `init` for parameters of initialisation.
+///
+STATIC mp_obj_t pyb_uart_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
+ // check arguments
+ mp_arg_check_num(n_args, n_kw, 1, MP_ARRAY_SIZE(pyb_uart_init_args), true);
+
+ // work out port
+ pyb_uart_t uart_id = mp_obj_get_int(args[0]);
+
+ if (uart_id < PYB_UART_1 || uart_id > MP_ARRAY_SIZE(MP_STATE_PORT(pyb_uart_obj_all))) {
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable));
+ }
+
+ // create object
+ pyb_uart_obj_t *self;
+ if (MP_STATE_PORT(pyb_uart_obj_all)[uart_id - 1] == NULL) {
+ // create new UART object
+ self = m_new0(pyb_uart_obj_t, 1);
+ self->base.type = &pyb_uart_type;
+ self->uart_id = uart_id;
+ self->enabled = false;
+ MP_STATE_PORT(pyb_uart_obj_all)[uart_id - 1] = self;
+ } else {
+ // reference existing UART object
+ self = MP_STATE_PORT(pyb_uart_obj_all)[uart_id - 1];
+ }
+
+ if (n_args > 1 || n_kw > 0) {
+ // start the peripheral
+ mp_map_t kw_args;
+ mp_map_init_fixed_table(&kw_args, n_kw, args + n_args);
+ pyb_uart_init_helper(self, n_args - 1, args + 1, &kw_args);
+ } else if (!self->enabled) {
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, mpexception_num_type_invalid_arguments));
+ }
+
+ return self;
+}
+
+STATIC mp_obj_t pyb_uart_init(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
+ return pyb_uart_init_helper(args[0], n_args - 1, args + 1, kw_args);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_uart_init_obj, 1, pyb_uart_init);
+
+/// \method deinit()
+/// Turn off the UART bus.
+STATIC mp_obj_t pyb_uart_deinit(mp_obj_t self_in) {
+ pyb_uart_obj_t *self = self_in;
+ uint uartPerh;
+
+ switch (self->uart_id) {
+
+ case PYB_UART_1:
+ uartPerh = PRCM_UARTA0;
+ break;
+
+ case PYB_UART_2:
+ uartPerh = PRCM_UARTA1;
+ break;
+
+ default:
+ return mp_const_none;
+ }
+
+ self->enabled = false;
+ MAP_UARTIntDisable(self->reg, UART_INT_RX | UART_INT_RT);
+ MAP_UARTIntClear(self->reg, UART_INT_RX | UART_INT_RT);
+ MAP_UARTIntUnregister(self->reg);
+ MAP_UARTDisable(self->reg);
+ MAP_PRCMPeripheralClkDisable(uartPerh, PRCM_RUN_MODE_CLK | PRCM_SLP_MODE_CLK);
+
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_uart_deinit_obj, pyb_uart_deinit);
+
+/// \method any()
+/// Return `True` if any characters waiting, else `False`.
+STATIC mp_obj_t pyb_uart_any(mp_obj_t self_in) {
+ pyb_uart_obj_t *self = self_in;
+ if (uart_rx_any(self)) {
+ return mp_const_true;
+ } else {
+ return mp_const_false;
+ }
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_uart_any_obj, pyb_uart_any);
+
+/// \method writechar(char)
+/// Write a single character on the bus. `char` is an integer to write.
+/// Return value: `None`.
+STATIC mp_obj_t pyb_uart_writechar(mp_obj_t self_in, mp_obj_t char_in) {
+ pyb_uart_obj_t *self = self_in;
+
+ // get the character to write
+ uint8_t data = mp_obj_get_int(char_in);
+
+ // send the character
+ if (!uart_tx_char(self, data)) {
+ nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(ETIMEDOUT)));
+ }
+
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(pyb_uart_writechar_obj, pyb_uart_writechar);
+
+/// \method readchar()
+/// Receive a single character on the bus.
+/// Return value: The character read, as an integer. Returns -1 on timeout.
+STATIC mp_obj_t pyb_uart_readchar(mp_obj_t self_in) {
+ pyb_uart_obj_t *self = self_in;
+ if (uart_rx_wait(self, self->timeout)) {
+ return mp_obj_new_int(uart_rx_char(self));
+ } else {
+ // return -1 on timeout
+ return MP_OBJ_NEW_SMALL_INT(-1);
+ }
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_uart_readchar_obj, pyb_uart_readchar);
+
+STATIC const mp_map_elem_t pyb_uart_locals_dict_table[] = {
+ // instance methods
+
+ { MP_OBJ_NEW_QSTR(MP_QSTR_init), (mp_obj_t)&pyb_uart_init_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_deinit), (mp_obj_t)&pyb_uart_deinit_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_any), (mp_obj_t)&pyb_uart_any_obj },
+
+ /// \method read([nbytes])
+ { MP_OBJ_NEW_QSTR(MP_QSTR_read), (mp_obj_t)&mp_stream_read_obj },
+ /// \method readall()
+ { MP_OBJ_NEW_QSTR(MP_QSTR_readall), (mp_obj_t)&mp_stream_readall_obj },
+ /// \method readline()
+ { MP_OBJ_NEW_QSTR(MP_QSTR_readline), (mp_obj_t)&mp_stream_unbuffered_readline_obj},
+ /// \method readinto(buf[, nbytes])
+ { MP_OBJ_NEW_QSTR(MP_QSTR_readinto), (mp_obj_t)&mp_stream_readinto_obj },
+ /// \method write(buf)
+ { MP_OBJ_NEW_QSTR(MP_QSTR_write), (mp_obj_t)&mp_stream_write_obj },
+
+ { MP_OBJ_NEW_QSTR(MP_QSTR_writechar), (mp_obj_t)&pyb_uart_writechar_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_readchar), (mp_obj_t)&pyb_uart_readchar_obj },
+
+ // class constants
+ { MP_OBJ_NEW_QSTR(MP_QSTR_UART1), MP_OBJ_NEW_SMALL_INT(PYB_UART_1) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_UART2), MP_OBJ_NEW_SMALL_INT(PYB_UART_2) },
+
+ { MP_OBJ_NEW_QSTR(MP_QSTR_FLOW_NONE), MP_OBJ_NEW_SMALL_INT(UART_FLOWCONTROL_NONE) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_FLOW_TX), MP_OBJ_NEW_SMALL_INT(UART_FLOWCONTROL_TX) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_FLOW_RX), MP_OBJ_NEW_SMALL_INT(UART_FLOWCONTROL_RX) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_FLOW_TXRX), MP_OBJ_NEW_SMALL_INT(UART_FLOWCONTROL_TX | UART_FLOWCONTROL_RX) },
+};
+
+STATIC MP_DEFINE_CONST_DICT(pyb_uart_locals_dict, pyb_uart_locals_dict_table);
+
+STATIC mp_uint_t pyb_uart_read(mp_obj_t self_in, void *buf_in, mp_uint_t size, int *errcode) {
+ pyb_uart_obj_t *self = self_in;
+ byte *buf = buf_in;
+
+ // make sure we want at least 1 char
+ if (size == 0) {
+ return 0;
+ }
+
+ // wait for first char to become available
+ if (!uart_rx_wait(self, self->timeout)) {
+ // we can either return 0 to indicate EOF (then read() method returns b'')
+ // or return EAGAIN error to indicate non-blocking (then read() method returns None)
+ return 0;
+ }
+
+ // read the data
+ byte *orig_buf = buf;
+ for (;;) {
+ *buf++ = uart_rx_char(self);
+ if (--size == 0 || !uart_rx_wait(self, self->timeout_char)) {
+ // return number of bytes read
+ return buf - orig_buf;
+ }
+ }
+}
+
+STATIC mp_uint_t pyb_uart_write(mp_obj_t self_in, const void *buf_in, mp_uint_t size, int *errcode) {
+ pyb_uart_obj_t *self = self_in;
+ const char *buf = buf_in;
+
+ // write the data
+ if (!uart_tx_strn(self, buf, size)) {
+ nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(ETIMEDOUT)));
+ }
+ return size;
+}
+
+STATIC mp_uint_t pyb_uart_ioctl(mp_obj_t self_in, mp_uint_t request, mp_uint_t arg, int *errcode) {
+ pyb_uart_obj_t *self = self_in;
+ mp_uint_t ret;
+ if (request == MP_IOCTL_POLL) {
+ mp_uint_t flags = arg;
+ ret = 0;
+ if ((flags & MP_IOCTL_POLL_RD) && uart_rx_any(self)) {
+ ret |= MP_IOCTL_POLL_RD;
+ }
+ if ((flags & MP_IOCTL_POLL_WR) && MAP_UARTSpaceAvail(self->reg)) {
+ ret |= MP_IOCTL_POLL_WR;
+ }
+ } else {
+ *errcode = EINVAL;
+ ret = MP_STREAM_ERROR;
+ }
+ return ret;
+}
+
+STATIC const mp_stream_p_t uart_stream_p = {
+ .read = pyb_uart_read,
+ .write = pyb_uart_write,
+ .ioctl = pyb_uart_ioctl,
+ .is_text = false,
+};
+
+const mp_obj_type_t pyb_uart_type = {
+ { &mp_type_type },
+ .name = MP_QSTR_UART,
+ .print = pyb_uart_print,
+ .make_new = pyb_uart_make_new,
+ .getiter = mp_identity,
+ .iternext = mp_stream_unbuffered_iter,
+ .stream_p = &uart_stream_p,
+ .locals_dict = (mp_obj_t)&pyb_uart_locals_dict,
+};
diff --git a/cc3200/mods/pybuart.h b/cc3200/mods/pybuart.h
new file mode 100644
index 000000000..74298a83f
--- /dev/null
+++ b/cc3200/mods/pybuart.h
@@ -0,0 +1,45 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2013, 2014 Damien P. George
+ * Copyright (c) 2015 Daniel Campora
+ *
+ * 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.
+ */
+
+typedef enum {
+ PYB_UART_NONE = 0,
+ PYB_UART_1 = 1,
+ PYB_UART_2 = 2
+} pyb_uart_t;
+
+typedef struct _pyb_uart_obj_t pyb_uart_obj_t;
+extern const mp_obj_type_t pyb_uart_type;
+
+void uart_init0(void);
+bool uart_init(pyb_uart_obj_t *uart_obj, uint baudrate);
+void uart_deinit (void);
+bool uart_rx_any(pyb_uart_obj_t *uart_obj);
+int uart_rx_char(pyb_uart_obj_t *uart_obj);
+bool uart_tx_char(pyb_uart_obj_t *self, int c);
+bool uart_tx_strn(pyb_uart_obj_t *uart_obj, const char *str, uint len);
+void uart_tx_strn_cooked(pyb_uart_obj_t *uart_obj, const char *str, uint len);
+