summaryrefslogtreecommitdiff
path: root/shared-module
diff options
context:
space:
mode:
Diffstat (limited to 'shared-module')
-rw-r--r--shared-module/audioio/Mixer.c341
-rw-r--r--shared-module/audioio/Mixer.h75
-rw-r--r--shared-module/audioio/WaveFile.c26
-rw-r--r--shared-module/audioio/__init__.c125
-rw-r--r--shared-module/audioio/__init__.h17
-rw-r--r--shared-module/bitbangio/SPI.c3
-rw-r--r--shared-module/bleio/Address.h40
-rw-r--r--shared-module/bleio/AdvertisementData.h85
-rw-r--r--shared-module/bleio/Characteristic.h52
-rw-r--r--shared-module/bleio/Device.h45
-rw-r--r--shared-module/bleio/ScanEntry.h40
-rw-r--r--shared-module/bleio/Scanner.h39
-rw-r--r--shared-module/bleio/Service.h44
-rw-r--r--shared-module/displayio/Sprite.c2
-rw-r--r--shared-module/network/__init__.c95
-rw-r--r--shared-module/network/__init__.h90
-rw-r--r--shared-module/os/__init__.c22
-rw-r--r--shared-module/socket/__init__.c0
-rw-r--r--shared-module/storage/__init__.c26
-rw-r--r--shared-module/usb_hid/Device.c88
-rw-r--r--shared-module/usb_hid/Device.h55
-rw-r--r--shared-module/usb_hid/__init__.c154
-rw-r--r--shared-module/wiznet/__init__.c0
-rw-r--r--shared-module/wiznet/wiznet5k.c406
-rw-r--r--shared-module/wiznet/wiznet5k.h69
25 files changed, 1931 insertions, 8 deletions
diff --git a/shared-module/audioio/Mixer.c b/shared-module/audioio/Mixer.c
new file mode 100644
index 000000000..8020a621e
--- /dev/null
+++ b/shared-module/audioio/Mixer.c
@@ -0,0 +1,341 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 Scott Shawcroft for Adafruit Industries
+ *
+ * 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 "shared-bindings/audioio/Mixer.h"
+
+#include <stdint.h>
+
+#include "py/runtime.h"
+#include "shared-module/audioio/__init__.h"
+#include "shared-module/audioio/RawSample.h"
+
+void common_hal_audioio_mixer_construct(audioio_mixer_obj_t* self,
+ uint8_t voice_count,
+ uint32_t buffer_size,
+ uint8_t bits_per_sample,
+ bool samples_signed,
+ uint8_t channel_count,
+ uint32_t sample_rate) {
+ self->len = buffer_size / 2 / sizeof(uint32_t) * sizeof(uint32_t);
+
+ self->first_buffer = m_malloc(self->len, false);
+ if (self->first_buffer == NULL) {
+ common_hal_audioio_mixer_deinit(self);
+ mp_raise_msg(&mp_type_MemoryError, translate("Couldn't allocate first buffer"));
+ }
+
+ self->second_buffer = m_malloc(self->len, false);
+ if (self->second_buffer == NULL) {
+ common_hal_audioio_mixer_deinit(self);
+ mp_raise_msg(&mp_type_MemoryError, translate("Couldn't allocate second buffer"));
+ }
+
+ self->bits_per_sample = bits_per_sample;
+ self->samples_signed = samples_signed;
+ self->channel_count = channel_count;
+ self->sample_rate = sample_rate;
+ self->voice_count = voice_count;
+
+ for (uint8_t i = 0; i < self->voice_count; i++) {
+ self->voice[i].sample = NULL;
+ }
+}
+
+void common_hal_audioio_mixer_deinit(audioio_mixer_obj_t* self) {
+ self->first_buffer = NULL;
+ self->second_buffer = NULL;
+}
+
+bool common_hal_audioio_mixer_deinited(audioio_mixer_obj_t* self) {
+ return self->first_buffer == NULL;
+}
+
+uint32_t common_hal_audioio_mixer_get_sample_rate(audioio_mixer_obj_t* self) {
+ return self->sample_rate;
+}
+
+void common_hal_audioio_mixer_play(audioio_mixer_obj_t* self, mp_obj_t sample, uint8_t v, bool loop) {
+ if (v >= self->voice_count) {
+ mp_raise_ValueError(translate("Voice index too high"));
+ }
+ if (audiosample_sample_rate(sample) != self->sample_rate) {
+ mp_raise_ValueError(translate("The sample's sample rate does not match the mixer's"));
+ }
+ if (audiosample_channel_count(sample) != self->channel_count) {
+ mp_raise_ValueError(translate("The sample's channel count does not match the mixer's"));
+ }
+ if (audiosample_bits_per_sample(sample) != self->bits_per_sample) {
+ mp_raise_ValueError(translate("The sample's bits_per_sample does not match the mixer's"));
+ }
+ bool single_buffer;
+ bool samples_signed;
+ uint32_t max_buffer_length;
+ uint8_t spacing;
+ audiosample_get_buffer_structure(sample, false, &single_buffer, &samples_signed,
+ &max_buffer_length, &spacing);
+ if (samples_signed != self->samples_signed) {
+ mp_raise_ValueError(translate("The sample's signedness does not match the mixer's"));
+ }
+ audioio_mixer_voice_t* voice = &self->voice[v];
+ voice->sample = sample;
+ voice->loop = loop;
+
+ audiosample_reset_buffer(sample, false, 0);
+ audioio_get_buffer_result_t result = audiosample_get_buffer(sample, false, 0, (uint8_t**) &voice->remaining_buffer, &voice->buffer_length);
+ // Track length in terms of words.
+ voice->buffer_length /= sizeof(uint32_t);
+ voice->more_data = result == GET_BUFFER_MORE_DATA;
+}
+
+void common_hal_audioio_mixer_stop_voice(audioio_mixer_obj_t* self, uint8_t voice) {
+ self->voice[voice].sample = NULL;
+}
+
+bool common_hal_audioio_mixer_get_playing(audioio_mixer_obj_t* self) {
+ for (int32_t v = 0; v < self->voice_count; v++) {
+ if (self->voice[v].sample != NULL) {
+ return true;
+ }
+ }
+ return false;
+}
+
+void audioio_mixer_reset_buffer(audioio_mixer_obj_t* self,
+ bool single_channel,
+ uint8_t channel) {
+ for (int32_t i = 0; i < self->voice_count; i++) {
+ self->voice[i].sample = NULL;
+ }
+}
+
+uint32_t add8signed(uint32_t a, uint32_t b) {
+ #if (defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1))
+ return __QADD8(a, b);
+ #else
+ uint32_t result = 0;
+ for (int8_t i = 0; i < 4; i++) {
+ int8_t ai = a >> (sizeof(int8_t) * 8 * i);
+ int8_t bi = b >> (sizeof(int8_t) * 8 * i);
+ int32_t intermediate = (int32_t) ai + bi;
+ if (intermediate > CHAR_MAX) {
+ intermediate = CHAR_MAX;
+ } else if (intermediate < CHAR_MIN) {
+ //intermediate = CHAR_MIN;
+ }
+ result |= (((uint32_t) intermediate) & 0xff) << (sizeof(int8_t) * 8 * i);
+ }
+ return result;
+ #endif
+}
+
+uint32_t add8unsigned(uint32_t a, uint32_t b) {
+ #if (defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1))
+ // Subtract out the DC offset, add and then shift back.
+ a = __USUB8(a, 0x80808080);
+ b = __USUB8(b, 0x80808080);
+ uint32_t sum = __QADD8(a, b);
+ return __UADD8(sum, 0x80808080);
+ #else
+ uint32_t result = 0;
+ for (int8_t i = 0; i < 4; i++) {
+ int8_t ai = (a >> (sizeof(uint8_t) * 8 * i)) - 128;
+ int8_t bi = (b >> (sizeof(uint8_t) * 8 * i)) - 128;
+ int32_t intermediate = (int32_t) ai + bi;
+ if (intermediate > UCHAR_MAX) {
+ intermediate = UCHAR_MAX;
+ }
+ result |= ((uint8_t) intermediate + 128) << (sizeof(uint8_t) * 8 * i);
+ }
+ return result;
+ #endif
+}
+
+uint32_t add16signed(uint32_t a, uint32_t b) {
+ #if (defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1))
+ return __QADD16(a, b);
+ #else
+ uint32_t result = 0;
+ for (int8_t i = 0; i < 2; i++) {
+ int16_t ai = a >> (sizeof(int16_t) * 8 * i);
+ int16_t bi = b >> (sizeof(int16_t) * 8 * i);
+ int32_t intermediate = (int32_t) ai + bi;
+ if (intermediate > SHRT_MAX) {
+ intermediate = SHRT_MAX;
+ } else if (intermediate < SHRT_MIN) {
+ intermediate = SHRT_MIN;
+ }
+ result |= (((uint32_t) intermediate) & 0xffff) << (sizeof(int16_t) * 8 * i);
+ }
+ return result;
+ #endif
+}
+
+uint32_t add16unsigned(uint32_t a, uint32_t b) {
+ #if (defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1))
+ // Subtract out the DC offset, add and then shift back.
+ a = __USUB16(a, 0x80008000);
+ b = __USUB16(b, 0x80008000);
+ uint32_t sum = __QADD16(a, b);
+ return __UADD16(sum, 0x80008000);
+ #else
+ uint32_t result = 0;
+ for (int8_t i = 0; i < 2; i++) {
+ int16_t ai = (a >> (sizeof(uint16_t) * 8 * i)) - 0x8000;
+ int16_t bi = (b >> (sizeof(uint16_t) * 8 * i)) - 0x8000;
+ int32_t intermediate = (int32_t) ai + bi;
+ if (intermediate > USHRT_MAX) {
+ intermediate = USHRT_MAX;
+ }
+ result |= ((uint16_t) intermediate + 0x8000) << (sizeof(int16_t) * 8 * i);
+ }
+ return result;
+ #endif
+}
+
+audioio_get_buffer_result_t audioio_mixer_get_buffer(audioio_mixer_obj_t* self,
+ bool single_channel,
+ uint8_t channel,
+ uint8_t** buffer,
+ uint32_t* buffer_length) {
+ if (!single_channel) {
+ channel = 0;
+ }
+
+ uint32_t channel_read_count = self->left_read_count;
+ if (channel == 1) {
+ channel_read_count = self->right_read_count;
+ }
+ *buffer_length = self->len;
+
+ bool need_more_data = self->read_count == channel_read_count;
+ if (need_more_data) {
+ uint32_t* word_buffer;
+ if (self->use_first_buffer) {
+ *buffer = (uint8_t*) self->first_buffer;
+ word_buffer = self->first_buffer;
+ } else {
+ *buffer = (uint8_t*) self->second_buffer;
+ word_buffer = self->second_buffer;
+ }
+ self->use_first_buffer = !self->use_first_buffer;
+ bool voices_active = false;
+ for (int32_t v = 0; v < self->voice_count; v++) {
+ audioio_mixer_voice_t* voice = &self->voice[v];
+
+ uint32_t j = 0;
+ bool voice_done = voice->sample == NULL;
+ for (uint32_t i = 0; i < self->len / sizeof(uint32_t); i++) {
+ if (!voice_done && j >= voice->buffer_length) {
+ if (!voice->more_data) {
+ if (voice->loop) {
+ audiosample_reset_buffer(voice->sample, false, 0);
+ } else {
+ voice->sample = NULL;
+ voice_done = true;
+ }
+ }
+ if (!voice_done) {
+ // Load another buffer
+ audioio_get_buffer_result_t result = audiosample_get_buffer(voice->sample, false, 0, (uint8_t**) &voice->remaining_buffer, &voice->buffer_length);
+ // Track length in terms of words.
+ voice->buffer_length /= sizeof(uint32_t);
+ voice->more_data = result == GET_BUFFER_MORE_DATA;
+ j = 0;
+ }
+ }
+ // First active voice gets copied over verbatim.
+ uint32_t sample_value;
+ if (voice_done) {
+ // Exit early if another voice already set all samples once.
+ if (voices_active) {
+ continue;
+ }
+ sample_value = 0;
+ if (!self->samples_signed) {
+ if (self->bits_per_sample == 8) {
+ sample_value = 0x7f7f7f7f;
+ } else {
+ sample_value = 0x7fff7fff;
+ }
+ }
+ } else {
+ sample_value = voice->remaining_buffer[j];
+ }
+
+ if (!voices_active) {
+ word_buffer[i] = sample_value;
+ } else {
+ if (self->bits_per_sample == 8) {
+ if (self->samples_signed) {
+ word_buffer[i] = add8signed(word_buffer[i], sample_value);
+ } else {
+ word_buffer[i] = add8unsigned(word_buffer[i], sample_value);
+ }
+ } else {
+ if (self->samples_signed) {
+ word_buffer[i] = add16signed(word_buffer[i], sample_value);
+ } else {
+ word_buffer[i] = add16unsigned(word_buffer[i], sample_value);
+ }
+ }
+ }
+ j++;
+ }
+ voice->buffer_length -= j;
+ voice->remaining_buffer += j;
+
+ voices_active = true;
+ }
+
+ self->read_count += 1;
+ } else if (!self->use_first_buffer) {
+ *buffer = (uint8_t*) self->first_buffer;
+ } else {
+ *buffer = (uint8_t*) self->second_buffer;
+ }
+
+
+ if (channel == 0) {
+ self->left_read_count += 1;
+ } else if (channel == 1) {
+ self->right_read_count += 1;
+ *buffer = *buffer + self->bits_per_sample / 8;
+ }
+ return GET_BUFFER_MORE_DATA;
+}
+
+void audioio_mixer_get_buffer_structure(audioio_mixer_obj_t* self, bool single_channel,
+ bool* single_buffer, bool* samples_signed,
+ uint32_t* max_buffer_length, uint8_t* spacing) {
+ *single_buffer = false;
+ *samples_signed = self->samples_signed;
+ *max_buffer_length = self->len;
+ if (single_channel) {
+ *spacing = self->channel_count;
+ } else {
+ *spacing = 1;
+ }
+}
diff --git a/shared-module/audioio/Mixer.h b/shared-module/audioio/Mixer.h
new file mode 100644
index 000000000..6a88fe0bd
--- /dev/null
+++ b/shared-module/audioio/Mixer.h
@@ -0,0 +1,75 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 Scott Shawcroft
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef MICROPY_INCLUDED_SHARED_MODULE_AUDIOIO_MIXER_H
+#define MICROPY_INCLUDED_SHARED_MODULE_AUDIOIO_MIXER_H
+
+#include "py/obj.h"
+
+#include "shared-module/audioio/__init__.h"
+
+typedef struct {
+ mp_obj_t sample;
+ bool loop;
+ bool more_data;
+ uint32_t* remaining_buffer;
+ uint32_t buffer_length;
+} audioio_mixer_voice_t;
+
+typedef struct {
+ mp_obj_base_t base;
+ uint32_t* first_buffer;
+ uint32_t* second_buffer;
+ uint32_t len; // in words
+ uint8_t bits_per_sample;
+ bool use_first_buffer;
+ bool samples_signed;
+ uint8_t channel_count;
+ uint32_t sample_rate;
+
+ uint32_t read_count;
+ uint32_t left_read_count;
+ uint32_t right_read_count;
+
+ uint8_t voice_count;
+ audioio_mixer_voice_t voice[];
+} audioio_mixer_obj_t;
+
+
+// These are not available from Python because it may be called in an interrupt.
+void audioio_mixer_reset_buffer(audioio_mixer_obj_t* self,
+ bool single_channel,
+ uint8_t channel);
+audioio_get_buffer_result_t audioio_mixer_get_buffer(audioio_mixer_obj_t* self,
+ bool single_channel,
+ uint8_t channel,
+ uint8_t** buffer,
+ uint32_t* buffer_length); // length in bytes
+void audioio_mixer_get_buffer_structure(audioio_mixer_obj_t* self, bool single_channel,
+ bool* single_buffer, bool* samples_signed,
+ uint32_t* max_buffer_length, uint8_t* spacing);
+
+#endif // MICROPY_INCLUDED_SHARED_MODULE_AUDIOIO_MIXER_H
diff --git a/shared-module/audioio/WaveFile.c b/shared-module/audioio/WaveFile.c
index 7efad05e0..d5dd9419c 100644
--- a/shared-module/audioio/WaveFile.c
+++ b/shared-module/audioio/WaveFile.c
@@ -141,6 +141,14 @@ void common_hal_audioio_wavefile_set_sample_rate(audioio_wavefile_obj_t* self,
self->sample_rate = sample_rate;
}
+uint8_t common_hal_audioio_wavefile_get_bits_per_sample(audioio_wavefile_obj_t* self) {
+ return self->bits_per_sample;
+}
+
+uint8_t common_hal_audioio_wavefile_get_channel_count(audioio_wavefile_obj_t* self) {
+ return self->channel_count;
+}
+
bool audioio_wavefile_samples_signed(audioio_wavefile_obj_t* self) {
return self->bits_per_sample > 8;
}
@@ -200,13 +208,29 @@ audioio_get_buffer_result_t audioio_wavefile_get_buffer(audioio_wavefile_obj_t*
if (f_read(&self->file->fp, *buffer, num_bytes_to_load, &length_read) != FR_OK) {
return GET_BUFFER_ERROR;
}
+ self->bytes_remaining -= length_read;
+ // Pad the last buffer to word align it.
+ if (self->bytes_remaining == 0 && length_read % sizeof(uint32_t) != 0) {
+ uint32_t pad = length_read % sizeof(uint32_t);
+ length_read += pad;
+ if (self->bits_per_sample == 8) {
+ for (uint32_t i = 0; i < pad; i++) {
+ ((uint8_t*) (*buffer))[length_read / sizeof(uint8_t) - i - 1] = 0x80;
+ }
+ } else if (self->bits_per_sample == 16) {
+ // We know the buffer is aligned because we allocated it onto the heap ourselves.
+ #pragma GCC diagnostic push
+ #pragma GCC diagnostic ignored "-Wcast-align"
+ ((int16_t*) (*buffer))[length_read / sizeof(int16_t) - 1] = 0;
+ #pragma GCC diagnostic pop
+ }
+ }
*buffer_length = length_read;
if (self->buffer_index % 2 == 1) {
self->second_buffer_length = length_read;
} else {
self->buffer_length = length_read;
}
- self->bytes_remaining -= length_read;
self->buffer_index += 1;
self->read_count += 1;
}
diff --git a/shared-module/audioio/__init__.c b/shared-module/audioio/__init__.c
new file mode 100644
index 000000000..b87b06a83
--- /dev/null
+++ b/shared-module/audioio/__init__.c
@@ -0,0 +1,125 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 Scott Shawcroft for Adafruit Industries
+ *
+ * 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 "shared-module/audioio/__init__.h"
+
+#include "py/obj.h"
+#include "shared-bindings/audioio/Mixer.h"
+#include "shared-bindings/audioio/RawSample.h"
+#include "shared-bindings/audioio/WaveFile.h"
+#include "shared-module/audioio/Mixer.h"
+#include "shared-module/audioio/RawSample.h"
+#include "shared-module/audioio/WaveFile.h"
+
+uint32_t audiosample_sample_rate(mp_obj_t sample_obj) {
+ if (MP_OBJ_IS_TYPE(sample_obj, &audioio_rawsample_type)) {
+ audioio_rawsample_obj_t* sample = MP_OBJ_TO_PTR(sample_obj);
+ return sample->sample_rate;
+ } else if (MP_OBJ_IS_TYPE(sample_obj, &audioio_wavefile_type)) {
+ audioio_wavefile_obj_t* file = MP_OBJ_TO_PTR(sample_obj);
+ return file->sample_rate;
+ } else if (MP_OBJ_IS_TYPE(sample_obj, &audioio_mixer_type)) {
+ audioio_mixer_obj_t* mixer = MP_OBJ_TO_PTR(sample_obj);
+ return mixer->sample_rate;
+ }
+ return 16000;
+}
+
+uint8_t audiosample_bits_per_sample(mp_obj_t sample_obj) {
+ if (MP_OBJ_IS_TYPE(sample_obj, &audioio_rawsample_type)) {
+ audioio_rawsample_obj_t* sample = MP_OBJ_TO_PTR(sample_obj);
+ return sample->bits_per_sample;
+ } else if (MP_OBJ_IS_TYPE(sample_obj, &audioio_wavefile_type)) {
+ audioio_wavefile_obj_t* file = MP_OBJ_TO_PTR(sample_obj);
+ return file->bits_per_sample;
+ } else if (MP_OBJ_IS_TYPE(sample_obj, &audioio_mixer_type)) {
+ audioio_mixer_obj_t* mixer = MP_OBJ_TO_PTR(sample_obj);
+ return mixer->bits_per_sample;
+ }
+ return 8;
+}
+
+uint8_t audiosample_channel_count(mp_obj_t sample_obj) {
+ if (MP_OBJ_IS_TYPE(sample_obj, &audioio_rawsample_type)) {
+ audioio_rawsample_obj_t* sample = MP_OBJ_TO_PTR(sample_obj);
+ return sample->channel_count;
+ } else if (MP_OBJ_IS_TYPE(sample_obj, &audioio_wavefile_type)) {
+ audioio_wavefile_obj_t* file = MP_OBJ_TO_PTR(sample_obj);
+ return file->channel_count;
+ } else if (MP_OBJ_IS_TYPE(sample_obj, &audioio_mixer_type)) {
+ audioio_mixer_obj_t* mixer = MP_OBJ_TO_PTR(sample_obj);
+ return mixer->channel_count;
+ }
+ return 1;
+}
+
+void audiosample_reset_buffer(mp_obj_t sample_obj, bool single_channel, uint8_t audio_channel) {
+ if (MP_OBJ_IS_TYPE(sample_obj, &audioio_rawsample_type)) {
+ audioio_rawsample_obj_t* sample = MP_OBJ_TO_PTR(sample_obj);
+ audioio_rawsample_reset_buffer(sample, single_channel, audio_channel);
+ } else if (MP_OBJ_IS_TYPE(sample_obj, &audioio_wavefile_type)) {
+ audioio_wavefile_obj_t* file = MP_OBJ_TO_PTR(sample_obj);
+ audioio_wavefile_reset_buffer(file, single_channel, audio_channel);
+ } else if (MP_OBJ_IS_TYPE(sample_obj, &audioio_mixer_type)) {
+ audioio_mixer_obj_t* file = MP_OBJ_TO_PTR(sample_obj);
+ audioio_mixer_reset_buffer(file, single_channel, audio_channel);
+ }
+}
+
+audioio_get_buffer_result_t audiosample_get_buffer(mp_obj_t sample_obj,
+ bool single_channel,
+ uint8_t channel,
+ uint8_t** buffer, uint32_t* buffer_length) {
+ if (MP_OBJ_IS_TYPE(sample_obj, &audioio_rawsample_type)) {
+ audioio_rawsample_obj_t* sample = MP_OBJ_TO_PTR(sample_obj);
+ return audioio_rawsample_get_buffer(sample, single_channel, channel, buffer, buffer_length);
+ } else if (MP_OBJ_IS_TYPE(sample_obj, &audioio_wavefile_type)) {
+ audioio_wavefile_obj_t* file = MP_OBJ_TO_PTR(sample_obj);
+ return audioio_wavefile_get_buffer(file, single_channel, channel, buffer, buffer_length);
+ } else if (MP_OBJ_IS_TYPE(sample_obj, &audioio_mixer_type)) {
+ audioio_mixer_obj_t* file = MP_OBJ_TO_PTR(sample_obj);
+ return audioio_mixer_get_buffer(file, single_channel, channel, buffer, buffer_length);
+ }
+ return GET_BUFFER_DONE;
+}
+
+void audiosample_get_buffer_structure(mp_obj_t sample_obj, bool single_channel,
+ bool* single_buffer, bool* samples_signed,
+ uint32_t* max_buffer_length, uint8_t* spacing) {
+ if (MP_OBJ_IS_TYPE(sample_obj, &audioio_rawsample_type)) {
+ audioio_rawsample_obj_t* sample = MP_OBJ_TO_PTR(sample_obj);
+ audioio_rawsample_get_buffer_structure(sample, single_channel, single_buffer,
+ samples_signed, max_buffer_length, spacing);
+ } else if (MP_OBJ_IS_TYPE(sample_obj, &audioio_wavefile_type)) {
+ audioio_wavefile_obj_t* file = MP_OBJ_TO_PTR(sample_obj);
+ audioio_wavefile_get_buffer_structure(file, single_channel, single_buffer, samples_signed,
+ max_buffer_length, spacing);
+ } else if (MP_OBJ_IS_TYPE(sample_obj, &audioio_mixer_type)) {
+ audioio_mixer_obj_t* file = MP_OBJ_TO_PTR(sample_obj);
+ audioio_mixer_get_buffer_structure(file, single_channel, single_buffer, samples_signed,
+ max_buffer_length, spacing);
+ }
+}
diff --git a/shared-module/audioio/__init__.h b/shared-module/audioio/__init__.h
index 2491beb12..c805f3116 100644
--- a/shared-module/audioio/__init__.h
+++ b/shared-module/audioio/__init__.h
@@ -27,10 +27,27 @@
#ifndef MICROPY_INCLUDED_SHARED_MODULE_AUDIOIO__INIT__H
#define MICROPY_INCLUDED_SHARED_MODULE_AUDIOIO__INIT__H
+#include <stdbool.h>
+#include <stdint.h>
+
+#include "py/obj.h"
+
typedef enum {
GET_BUFFER_DONE, // No more data to read
GET_BUFFER_MORE_DATA, // More data to read.
GET_BUFFER_ERROR, // Error while reading data.
} audioio_get_buffer_result_t;
+uint32_t audiosample_sample_rate(mp_obj_t sample_obj);
+uint8_t audiosample_bits_per_sample(mp_obj_t sample_obj);
+uint8_t audiosample_channel_count(mp_obj_t sample_obj);
+void audiosample_reset_buffer(mp_obj_t sample_obj, bool single_channel, uint8_t audio_channel);
+audioio_get_buffer_result_t audiosample_get_buffer(mp_obj_t sample_obj,
+ bool single_channel,
+ uint8_t channel,
+ uint8_t** buffer, uint32_t* buffer_length);
+void audiosample_get_buffer_structure(mp_obj_t sample_obj, bool single_channel,
+ bool* single_buffer, bool* samples_signed,
+ uint32_t* max_buffer_length, uint8_t* spacing);
+
#endif // MICROPY_INCLUDED_SHARED_MODULE_AUDIOIO__INIT__H
diff --git a/shared-module/bitbangio/SPI.c b/shared-module/bitbangio/SPI.c
index 9e4508355..6d3a28523 100644
--- a/shared-module/bitbangio/SPI.c
+++ b/shared-module/bitbangio/SPI.c
@@ -24,8 +24,7 @@
* THE SOFTWARE.
*/
-#include "mpconfigport.h"
-
+#include "py/mpconfig.h"
#include "py/obj.h"
#include "py/runtime.h"
diff --git a/shared-module/bleio/Address.h b/shared-module/bleio/Address.h
new file mode 100644
index 000000000..f0998c163
--- /dev/null
+++ b/shared-module/bleio/Address.h
@@ -0,0 +1,40 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 Artur Pacholec
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef MICROPY_INCLUDED_SHARED_MODULE_BLEIO_ADDRESS_H
+#define MICROPY_INCLUDED_SHARED_MODULE_BLEIO_ADDRESS_H
+
+#include "shared-bindings/bleio/AddressType.h"
+
+#define BLEIO_ADDRESS_BYTES 6
+
+typedef struct {
+ mp_obj_base_t base;
+ bleio_address_type_t type;
+ uint8_t value[BLEIO_ADDRESS_BYTES];
+} bleio_address_obj_t;
+
+#endif // MICROPY_INCLUDED_SHARED_MODULE_BLEIO_ADDRESS_H
diff --git a/shared-module/bleio/AdvertisementData.h b/shared-module/bleio/AdvertisementData.h
new file mode 100644
index 000000000..738d53b23
--- /dev/null
+++ b/shared-module/bleio/AdvertisementData.h
@@ -0,0 +1,85 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 Artur Pacholec
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef MICROPY_INCLUDED_SHARED_MODULE_BLEIO_ADVERTISEMENTDATA_H
+#define MICROPY_INCLUDED_SHARED_MODULE_BLEIO_ADVERTISEMENTDATA_H
+
+#include "py/obj.h"
+
+// Taken from https://www.bluetooth.com/specifications/assigned-numbers/generic-access-profile
+enum {
+ AdFlags = 0x01,
+ AdIncompleteListOf16BitServiceClassUUIDs = 0x02,
+ AdCompleteListOf16BitServiceClassUUIDs = 0x03,
+ AdIncompleteListOf32BitServiceClassUUIDs = 0x04,
+ AdCompleteListOf32BitServiceClassUUIDs = 0x05,
+ AdIncompleteListOf128BitServiceClassUUIDs = 0x06,
+ AdCompleteListOf128BitServiceClassUUIDs = 0x07,
+ AdShortenedLocalName = 0x08,
+ AdCompleteLocalName = 0x09,
+ AdTxPowerLevel = 0x0A,
+ AdClassOfDevice = 0x0D,
+ AdSimplePairingHashC = 0x0E,
+ AdSimplePairingRandomizerR = 0x0F,
+ AdSecurityManagerTKValue = 0x10,
+ AdSecurityManagerOOBFlags = 0x11,
+ AdSlaveConnectionIntervalRange = 0x12,
+ AdListOf16BitServiceSolicitationUUIDs = 0x14,
+ AdListOf128BitServiceSolicitationUUIDs = 0x15,
+ AdServiceData = 0x16,
+ AdPublicTargetAddress = 0x17,
+ AdRandomTargetAddress = 0x18,
+ AdAppearance = 0x19,
+ AdAdvertisingInterval = 0x1A,
+ AdLEBluetoothDeviceAddress = 0x1B,
+ AdLERole = 0x1C,
+ AdSimplePairingHashC256 = 0x1D,
+ AdSimplePairingRandomizerR256 = 0x1E,
+ AdListOf32BitServiceSolicitationUUIDs = 0x1F,
+ AdServiceData32BitUUID = 0x20,
+ AdServiceData128BitUUID = 0x21,
+ AdLESecureConnectionsConfirmationValue = 0x22,
+ AdLESecureConnectionsRandomValue = 0x23,
+ AdURI = 0x24,
+ AdIndoorPositioning = 0x25,
+ AdTransportDiscoveryData = 0x26,
+ AdLESupportedFeatures = 0x27,
+ AdChannelMapUpdateIndication = 0x28,
+ AdPBADV = 0x29,
+ AdMeshMessage = 0x2A,
+ AdMeshBeacon = 0x2B,
+ Ad3DInformationData = 0x3D,
+ AdManufacturerSpecificData = 0xFF,
+};
+
+typedef struct {
+ mp_obj_t device_name;
+ mp_obj_t services;
+ mp_obj_t data;
+ bool connectable;
+} bleio_advertisement_data_t;
+
+#endif // MICROPY_INCLUDED_SHARED_MODULE_BLEIO_ADVERTISEMENTDATA_H
diff --git a/shared-module/bleio/Characteristic.h b/shared-module/bleio/Characteristic.h
new file mode 100644
index 000000000..94c43f81e
--- /dev/null
+++ b/shared-module/bleio/Characteristic.h
@@ -0,0 +1,52 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 Artur Pacholec
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef MICROPY_INCLUDED_SHARED_MODULE_BLEIO_CHARACTERISTIC_H
+#define MICROPY_INCLUDED_SHARED_MODULE_BLEIO_CHARACTERISTIC_H
+
+#include "shared-module/bleio/Service.h"
+#include "common-hal/bleio/UUID.h"
+
+typedef struct {
+ mp_obj_base_t base;
+ bleio_service_obj_t *service;
+ bleio_uuid_obj_t *uuid;
+ mp_obj_t value_data;
+ uint16_t handle;
+ struct {
+ bool broadcast : 1;
+ bool read : 1;
+ bool write_wo_resp : 1;
+ bool write : 1;
+ bool notify : 1;
+ bool indicate : 1;
+ } props;
+ uint16_t user_desc_handle;
+ uint16_t cccd_handle;
+ uint16_t sccd_handle;
+} bleio_characteristic_obj_t;
+
+#endif // MICROPY_INCLUDED_SHARED_MODULE_BLEIO_CHARACTERISTIC_H
diff --git a/shared-module/bleio/Device.h b/shared-module/bleio/Device.h
new file mode 100644
index 000000000..8d9ece5ef
--- /dev/null
+++ b/shared-module/bleio/Device.h
@@ -0,0 +1,45 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 Artur Pacholec
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef MICROPY_INCLUDED_SHARED_MODULE_BLEIO_DEVICE_H
+#define MICROPY_INCLUDED_SHARED_MODULE_BLEIO_DEVICE_H
+
+#include <stdbool.h>
+
+#include "shared-module/bleio/Address.h"
+
+typedef struct {
+ mp_obj_base_t base;
+ bool is_peripheral;
+ mp_obj_t name;
+ bleio_address_obj_t address;
+ volatile uint16_t conn_handle;
+ mp_obj_t service_list;
+ mp_obj_t notif_handler;
+ mp_obj_t conn_handler;
+} bleio_device_obj_t;
+
+#endif // MICROPY_INCLUDED_SHARED_MODULE_BLEIO_DEVICE_H
diff --git a/shared-module/bleio/ScanEntry.h b/shared-module/bleio/ScanEntry.h
new file mode 100644
index 000000000..2f01669e2
--- /dev/null
+++ b/shared-module/bleio/ScanEntry.h
@@ -0,0 +1,40 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 Artur Pacholec
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef MICROPY_INCLUDED_SHARED_MODULE_BLEIO_SCANENTRY_H
+#define MICROPY_INCLUDED_SHARED_MODULE_BLEIO_SCANENTRY_H
+
+#include "shared-module/bleio/Address.h"
+
+typedef struct {
+ mp_obj_base_t base;
+ bleio_address_obj_t address;
+ bool connectable;
+ int8_t rssi;
+ mp_obj_t data;
+} bleio_scanentry_obj_t;
+
+#endif // MICROPY_INCLUDED_SHARED_MODULE_BLEIO_SCANENTRY_H
diff --git a/shared-module/bleio/Scanner.h b/shared-module/bleio/Scanner.h
new file mode 100644
index 000000000..76f5e5866
--- /dev/null
+++ b/shared-module/bleio/Scanner.h
@@ -0,0 +1,39 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 Artur Pacholec
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef MICROPY_INCLUDED_SHARED_MODULE_BLEIO_SCANNER_H
+#define MICROPY_INCLUDED_SHARED_MODULE_BLEIO_SCANNER_H
+
+#include "py/obj.h"
+
+typedef struct {
+ mp_obj_base_t base;
+ mp_obj_t adv_reports;
+ uint16_t interval;
+ uint16_t window;
+} bleio_scanner_obj_t;
+
+#endif // MICROPY_INCLUDED_SHARED_MODULE_BLEIO_SCANNER_H
diff --git a/shared-module/bleio/Service.h b/shared-module/bleio/Service.h
new file mode 100644
index 000000000..ff506d3f3
--- /dev/null
+++ b/shared-module/bleio/Service.h
@@ -0,0 +1,44 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 Artur Pacholec
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef MICROPY_INCLUDED_SHARED_MODULE_BLEIO_SERVICE_H
+#define MICROPY_INCLUDED_SHARED_MODULE_BLEIO_SERVICE_H
+
+#include "common-hal/bleio/UUID.h"
+#include "shared-module/bleio/Device.h"
+
+typedef struct {
+ mp_obj_base_t base;
+ uint16_t handle;
+ bool is_secondary;
+ bleio_uuid_obj_t *uuid;
+ bleio_device_obj_t *device;
+ mp_obj_t char_list;
+ uint16_t start_handle;
+ uint16_t end_handle;
+} bleio_service_obj_t;
+
+#endif // MICROPY_INCLUDED_SHARED_MODULE_BLEIO_SERVICE_H
diff --git a/shared-module/displayio/Sprite.c b/shared-module/displayio/Sprite.c
index 4fe8d1ff6..87600f721 100644
--- a/shared-module/displayio/Sprite.c
+++ b/shared-module/displayio/Sprite.c
@@ -68,7 +68,7 @@ bool displayio_sprite_get_pixel(displayio_sprite_t *self, int16_t x, int16_t y,
if (y < 0 || y >= self->height || x >= self->width || x < 0) {
return false;
}
- uint32_t value;
+ uint32_t value = 0;
if (MP_OBJ_IS_TYPE(self->bitmap, &displayio_bitmap_type)) {
value = common_hal_displayio_bitmap_get_pixel(self->bitmap, x, y);
} else if (MP_OBJ_IS_TYPE(self->bitmap, &displayio_ondiskbitmap_type)) {
diff --git a/shared-module/network/__init__.c b/shared-module/network/__init__.c
new file mode 100644
index 000000000..a674e8478
--- /dev/null
+++ b/shared-module/network/__init__.c
@@ -0,0 +1,95 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 Nick Moore
+ *
+ * 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 "py/objlist.h"
+#include "py/runtime.h"
+#include "py/mphal.h"
+#include "py/mperrno.h"
+
+#include "shared-bindings/random/__init__.h"
+
+#include "shared-module/network/__init__.h"
+
+// mod_network_nic_list needs to be declared in mpconfigport.h
+
+
+void network_module_init(void) {
+ mp_obj_list_init(&MP_STATE_PORT(mod_network_nic_list), 0);
+}
+
+void network_module_deinit(void) {
+}
+
+void network_module_background(void) {
+ static uint32_t next_tick = 0;
+ uint32_t this_tick = ticks_ms;
+ if (this_tick < next_tick) return;
+ next_tick = this_tick + 1000;
+
+ 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->timer_tick != NULL) nic_type->timer_tick(nic);
+ }
+}
+
+void network_module_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_OBJ_FROM_PTR(&MP_STATE_PORT(mod_network_nic_list)), nic);
+}
+
+mp_obj_t network_module_find_nic(const uint8_t *ip) {
+ // find a NIC that is suited to given IP address
+ for (mp_uint_t i = 0; i < MP_STATE_PORT(mod_network_nic_list).len; i++) {
+ mp_obj_t nic = MP_STATE_PORT(mod_network_nic_list).items[i];
+ // TODO check IP suitability here
+ //mod_network_nic_type_t *nic_type = (mod_network_nic_type_t*)mp_obj_get_type(nic);
+ return nic;
+ }
+
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, translate("no available NIC")));
+}
+
+void network_module_create_random_mac_address(uint8_t *mac) {
+ uint32_t rb1 = shared_modules_random_getrandbits(24);
+ uint32_t rb2 = shared_modules_random_getrandbits(24);
+ // first octet has multicast bit (0) cleared and local bit (1) set
+ // everything else is just set randomly
+ mac[0] = ((uint8_t)(rb1 >> 16) & 0xfe) | 0x02;
+ mac[1] = (uint8_t)(rb1 >> 8);
+ mac[2] = (uint8_t)(rb1);
+ mac[3] = (uint8_t)(rb2 >> 16);
+ mac[4] = (uint8_t)(rb2 >> 8);
+ mac[5] = (uint8_t)(rb2);
+}
diff --git a/shared-module/network/__init__.h b/shared-module/network/__init__.h
new file mode 100644
index 000000000..00a3c3957
--- /dev/null
+++ b/shared-module/network/__init__.h
@@ -0,0 +1,90 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2013, 2014 Damien P. George
+ * Copyright (c) 2018 Nick Moore
+ *
+ * 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 network_module_create_random_mac_address(uint8_t *mac);
+
+#ifndef MICROPY_INCLUDED_SHARED_MODULE_NETWORK___INIT___H
+#define MICROPY_INCLUDED_SHARED_MODULE_NETWORK___INIT___H
+
+#define MOD_NETWORK_IPADDR_BUF_SIZE (4)
+
+#define MOD_NETWORK_AF_INET (2)
+#define MOD_NETWORK_AF_INET6 (10)
+
+#define MOD_NETWORK_SOCK_STREAM (1)
+#define MOD_NETWORK_SOCK_DGRAM (2)
+#define MOD_NETWORK_SOCK_RAW (3)
+
+struct _mod_network_socket_obj_t;
+
+typedef struct _mod_network_nic_type_t {
+ mp_obj_type_t base;
+
+ // API for non-socket operations
+ int (*gethostbyname)(mp_obj_t nic, const char *name, mp_uint_t len, uint8_t *ip_out);
+
+ // API for socket operations; return -1 on error
+ int (*socket)(struct _mod_network_socket_obj_t *socket, int *_errno);
+ void (*close)(struct _mod_network_socket_obj_t *socket);
+ int (*bind)(struct _mod_network_socket_obj_t *socket, byte *ip, mp_uint_t port, int *_errno);
+ int (*listen)(struct _mod_network_socket_obj_t *socket, mp_int_t backlog, int *_errno);
+ int (*accept)(struct _mod_network_socket_obj_t *socket, struct _mod_network_socket_obj_t *socket2, byte *ip, mp_uint_t *port, int *_errno);
+ int (*connect)(struct _mod_network_socket_obj_t *socket, byte *ip, mp_uint_t port, int *_errno);
+ mp_uint_t (*send)(struct _mod_network_socket_obj_t *socket, const byte *buf, mp_uint_t len, int *_errno);
+ mp_uint_t (*recv)(struct _mod_network_socket_obj_t *socket, byte *buf, mp_uint_t len, int *_errno);
+ mp_uint_t (*sendto)(struct _mod_network_socket_obj_t *socket, const byte *buf, mp_uint_t len, byte *ip, mp_uint_t port, int *_errno);
+ mp_uint_t (*recvfrom)(struct _mod_network_socket_obj_t *socket, byte *buf, mp_uint_t len, byte *ip, mp_uint_t *port, int *_errno);
+ int (*setsockopt)(struct _mod_network_socket_obj_t *socket, mp_uint_t level, mp_uint_t opt, const void *optval, mp_uint_t optlen, int *_errno);
+ int (*settimeout)(struct _mod_network_socket_obj_t *socket, mp_uint_t timeout_ms, int *_errno);
+ int (*ioctl)(struct _mod_network_socket_obj_t *socket, mp_uint_t request, mp_uint_t arg, int *_errno);
+ void (*timer_tick)(struct _mod_network_socket_obj_t *socket);
+} mod_network_nic_type_t;
+
+typedef struct _mod_network_socket_obj_t {
+ mp_obj_base_t base;
+ mp_obj_t nic;
+ mod_network_nic_type_t *nic_type;
+ union {
+ struct {
+ uint8_t domain;
+ uint8_t type;
+ int8_t fileno;
+ } u_param;
+ mp_uint_t u_state;
+ };
+} mod_network_socket_obj_t;
+
+extern const mod_network_nic_type_t mod_network_nic_type_wiznet5k;
+extern const mod_network_nic_type_t mod_network_nic_type_cc3k;
+
+void network_module_init(void);
+void network_module_deinit(void);
+void network_module_background(void);
+void network_module_register_nic(mp_obj_t nic);
+mp_obj_t network_module_find_nic(const uint8_t *ip);
+
+#endif // MICROPY_INCLUDED_SHARED_MODULE_NETWORK___INIT___H
diff --git a/shared-module/os/__init__.c b/shared-module/os/__init__.c
index a38f3781f..313893d97 100644
--- a/shared-module/os/__init__.c
+++ b/shared-module/os/__init__.c
@@ -50,6 +50,20 @@ STATIC mp_vfs_mount_t *lookup_path(const char* path, mp_obj_t *path_out) {
return vfs;
}
+// Strip off trailing slashes to please underlying libraries
+STATIC mp_vfs_mount_t *lookup_dir_path(const char* path, mp_obj_t *path_out) {
+ const char *p_out;
+ mp_vfs_mount_t *vfs = mp_vfs_lookup_path(path, &p_out);
+ if (vfs != MP_VFS_NONE && vfs != MP_VFS_ROOT) {
+ size_t len = strlen(p_out);
+ while (len > 1 && p_out[len - 1] == '/') {
+ len--;
+ }
+ *path_out = mp_obj_new_str_of_type(&mp_type_str, (const byte*)p_out, len);
+ }
+ return vfs;
+}
+
STATIC mp_obj_t mp_vfs_proxy_call(mp_vfs_mount_t *vfs, qstr meth_name, size_t n_args, const mp_obj_t *args) {
if (vfs == MP_VFS_NONE) {
// mount point not found
@@ -69,7 +83,7 @@ STATIC mp_obj_t mp_vfs_proxy_call(mp_vfs_mount_t *vfs, qstr meth_name, size_t n_
void common_hal_os_chdir(const char* path) {
mp_obj_t path_out;
- mp_vfs_mount_t *vfs = lookup_path(path, &path_out);
+ mp_vfs_mount_t *vfs = lookup_dir_path(path, &path_out);
MP_STATE_VM(vfs_cur) = vfs;
if (vfs == MP_VFS_ROOT) {
// If we change to the root dir and a VFS is mounted at the root then
@@ -93,7 +107,7 @@ mp_obj_t common_hal_os_getcwd(void) {
mp_obj_t common_hal_os_listdir(const char* path) {
mp_obj_t path_out;
- mp_vfs_mount_t *vfs = lookup_path(path, &path_out);
+ mp_vfs_mount_t *vfs = lookup_dir_path(path, &path_out);
mp_vfs_ilistdir_it_t iter;
mp_obj_t iter_obj = MP_OBJ_FROM_PTR(&iter);
@@ -120,7 +134,7 @@ mp_obj_t common_hal_os_listdir(const char* path) {
void common_hal_os_mkdir(const char* path) {
mp_obj_t path_out;
- mp_vfs_mount_t *vfs = lookup_path(path, &path_out);
+ mp_vfs_mount_t *vfs = lookup_dir_path(path, &path_out);
if (vfs == MP_VFS_ROOT || (vfs != MP_VFS_NONE && !strcmp(mp_obj_str_get_str(path_out), "/"))) {
mp_raise_OSError(MP_EEXIST);
}
@@ -146,7 +160,7 @@ void common_hal_os_rename(const char* old_path, const char* new_path) {
void common_hal_os_rmdir(const char* path) {
mp_obj_t path_out;
- mp_vfs_mount_t *vfs = lookup_path(path, &path_out);
+ mp_vfs_mount_t *vfs = lookup_dir_path(path, &path_out);
mp_vfs_proxy_call(vfs, MP_QSTR_rmdir, 1, &path_out);
}
diff --git a/shared-module/socket/__init__.c b/shared-module/socket/__init__.c
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/shared-module/socket/__init__.c
diff --git a/shared-module/storage/__init__.c b/shared-module/storage/__init__.c
index edce286b1..f09edd785 100644
--- a/shared-module/storage/__init__.c
+++ b/shared-module/storage/__init__.c
@@ -32,8 +32,12 @@
#include "py/mperrno.h"
#include "py/obj.h"
#include "py/runtime.h"
+#include "shared-bindings/microcontroller/__init__.h"
#include "shared-bindings/os/__init__.h"
#include "shared-bindings/storage/__init__.h"
+#include "supervisor/filesystem.h"
+#include "supervisor/flash.h"
+#include "supervisor/usb.h"
STATIC mp_obj_t mp_vfs_proxy_call(mp_vfs_mount_t *vfs, qstr meth_name, size_t n_args, const mp_obj_t *args) {
if (vfs == MP_VFS_NONE) {
@@ -138,3 +142,25 @@ void common_hal_storage_umount_path(const char* mount_path) {
mp_obj_t common_hal_storage_getmount(const char *mount_path) {
return storage_object_from_path(mount_path);
}
+
+void common_hal_storage_remount(const char *mount_path, bool readonly) {
+ if (strcmp(mount_path, "/") != 0) {
+ mp_raise_OSError(MP_EINVAL);
+ }
+
+ #ifdef USB_AVAILABLE
+ // TODO(dhalbert): is this is a good enough check? It checks for
+ // CDC enabled. There is no "MSC enabled" check.
+ if (usb_enabled()) {
+ mp_raise_RuntimeError(translate("Cannot remount '/' when USB is active."));
+ }
+ #endif
+
+ supervisor_flash_set_usb_writable(readonly);
+}
+
+void common_hal_storage_erase_filesystem(void) {
+ filesystem_init(false, true); // Force a re-format.
+ common_hal_mcu_reset();
+ // We won't actually get here, since we're resetting.
+}
diff --git a/shared-module/usb_hid/Device.c b/shared-module/usb_hid/Device.c
new file mode 100644
index 000000000..820e14ad0
--- /dev/null
+++ b/shared-module/usb_hid/Device.c
@@ -0,0 +1,88 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 hathach for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <string.h>
+#include "tick.h"
+#include "py/runtime.h"
+#include "shared-bindings/usb_hid/Device.h"
+#include "shared-module/usb_hid/Device.h"
+#include "supervisor/shared/translate.h"
+#include "tusb.h"
+
+uint8_t common_hal_usb_hid_device_get_usage_page(usb_hid_device_obj_t *self) {
+ return self->usage_page;
+}
+
+uint8_t common_hal_usb_hid_device_get_usage(usb_hid_device_obj_t *self) {
+ return self->usage;
+}
+
+void common_hal_usb_hid_device_send_report(usb_hid_device_obj_t *self, uint8_t* report, uint8_t len) {
+ if (len != self->report_length) {
+ mp_raise_ValueError_varg(translate("Buffer incorrect size. Should be %d bytes."), self->report_length);
+ }
+
+ // Wait until interface is ready, timeout = 2 seconds
+ uint64_t end_ticks = ticks_ms + 2000;
+ while ( (ticks_ms < end_ticks) && !tud_hid_generic_ready() ) { }
+
+ if ( !tud_hid_generic_ready() ) {
+ mp_raise_msg(&mp_type_OSError, translate("USB Busy"));
+ }
+
+ memcpy(self->report_buffer, report, len);
+
+ if ( !tud_hid_generic_report(self->report_id, self->report_buffer, len) ) {
+ mp_raise_msg(&mp_type_OSError, translate("USB Error"));
+ }
+}
+
+// Callbacks invoked when receive Get_Report request through control endpoint
+uint16_t tud_hid_generic_get_report_cb(uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen) {
+ // only support Input Report
+ if ( report_type != HID_REPORT_TYPE_INPUT ) return 0;
+
+ // index is ID-1
+ uint8_t idx = ( report_id ? (report_id-1) : 0 );
+
+ // fill buffer with current report
+ memcpy(buffer, usb_hid_devices[idx].report_buffer, reqlen);
+ return reqlen;
+}
+
+// Callbacks invoked when receive Set_Report request through control endpoint
+void tud_hid_generic_set_report_cb(uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize) {
+ // index is ID-1
+ uint8_t idx = ( report_id ? (report_id-1) : 0 );
+
+ if ( report_type == HID_REPORT_TYPE_OUTPUT ) {
+ // Check if it is Keyboard device
+ if ( (usb_hid_devices[idx].usage_page == HID_USAGE_PAGE_DESKTOP) && (usb_hid_devices[idx].usage == HID_USAGE_DESKTOP_KEYBOARD) ) {
+ // This is LED indicator (CapsLock, NumLock)
+ // TODO Light up some LED here
+ }
+ }
+}
diff --git a/shared-module/usb_hid/Device.h b/shared-module/usb_hid/Device.h
new file mode 100644
index 000000000..10f2ee897
--- /dev/null
+++ b/shared-module/usb_hid/Device.h
@@ -0,0 +1,55 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 hathach for Adafruit Industries
+ *
+ * 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 SHARED_MODULE_USB_HID_DEVICE_H
+#define SHARED_MODULE_USB_HID_DEVICE_H
+
+#include <stdint.h>
+#include <stdbool.h>
+
+#include "py/obj.h"
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+typedef struct {
+ mp_obj_base_t base;
+ uint8_t* report_buffer;
+ uint8_t report_id;
+ uint8_t report_length;
+ uint8_t usage_page;
+ uint8_t usage;
+} usb_hid_device_obj_t;
+
+
+extern usb_hid_device_obj_t usb_hid_devices[];
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif /* SHARED_MODULE_USB_HID_DEVICE_H */
diff --git a/shared-module/usb_hid/__init__.c b/shared-module/usb_hid/__init__.c
new file mode 100644
index 000000000..f14fdd41e
--- /dev/null
+++ b/shared-module/usb_hid/__init__.c
@@ -0,0 +1,154 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 hathach for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "py/obj.h"
+#include "py/mphal.h"
+#include "py/runtime.h"
+
+#include "genhdr/autogen_usb_descriptor.h"
+#include "shared-module/usb_hid/Device.h"
+#include "shared-bindings/usb_hid/Device.h"
+#include "tusb.h"
+
+#ifdef USB_HID_REPORT_ID_KEYBOARD
+static uint8_t keyboard_report_buffer[USB_HID_REPORT_LENGTH_KEYBOARD];
+#endif
+
+#ifdef USB_HID_REPORT_ID_MOUSE
+static uint8_t mouse_report_buffer[USB_HID_REPORT_LENGTH_MOUSE];
+#endif
+
+#ifdef USB_HID_REPORT_ID_CONSUMER
+static uint8_t consumer_report_buffer[USB_HID_REPORT_LENGTH_CONSUMER];
+#endif
+
+#ifdef USB_HID_REPORT_ID_SYS_CONTROL
+static uint8_t sys_control_report_buffer[USB_HID_REPORT_LENGTH_SYS_CONTROL];
+#endif
+
+#ifdef USB_HID_REPORT_ID_GAMEPAD
+static uint8_t gamepad_report_buffer[USB_HID_REPORT_LENGTH_GAMEPAD];
+#endif
+
+#ifdef USB_HID_REPORT_ID_DIGITIZER
+static uint8_t digitizer_report_buffer[USB_HID_REPORT_LENGTH_DIGITIZER];
+#endif
+
+usb_hid_device_obj_t usb_hid_devices[] = {
+#ifdef USB_HID_REPORT_ID_KEYBOARD
+ {
+ .base = { .type = &usb_hid_device_type } ,
+ .report_buffer = keyboard_report_buffer ,
+ .report_id = USB_HID_REPORT_ID_KEYBOARD ,
+ .report_length = USB_HID_REPORT_LENGTH_KEYBOARD ,
+ .usage_page = HID_USAGE_PAGE_DESKTOP ,
+ .usage = HID_USAGE_DESKTOP_KEYBOARD ,
+ },
+#endif
+
+#ifdef USB_HID_REPORT_ID_MOUSE
+ {
+ .base = { .type = &usb_hid_device_type } ,
+ .report_buffer = mouse_report_buffer ,
+ .report_id = USB_HID_REPORT_ID_MOUSE ,
+ .report_length = USB_HID_REPORT_LENGTH_MOUSE ,
+ .usage_page = HID_USAGE_PAGE_DESKTOP ,
+ .usage = HID_USAGE_DESKTOP_MOUSE ,
+ },
+#endif
+
+#ifdef USB_HID_REPORT_ID_CONSUMER
+ {
+ .base = { .type = &usb_hid_device_type } ,
+ .report_buffer = consumer_report_buffer ,
+ .report_id = USB_HID_REPORT_ID_CONSUMER ,
+ .report_length = USB_HID_REPORT_LENGTH_CONSUMER ,
+ .usage_page = HID_USAGE_PAGE_CONSUMER ,
+ .usage = HID_USAGE_CONSUMER_CONTROL ,
+ },
+#endif
+
+#ifdef USB_HID_REPORT_ID_SYS_CONTROL
+ {
+ .base = { .type = &usb_hid_device_type } ,
+ .report_buffer = sys_control_report_buffer ,
+ .report_id = USB_HID_REPORT_ID_SYS_CONTROL ,
+ .report_length = USB_HID_REPORT_LENGTH_SYS_CONTROL ,
+ .usage_page = HID_USAGE_PAGE_DESKTOP ,
+ .usage = HID_USAGE_DESKTOP_SYSTEM_CONTROL ,
+ },
+#endif
+
+#ifdef USB_HID_REPORT_ID_GAMEPAD
+ {
+ .base = { .type = &usb_hid_device_type } ,
+ .report_buffer = gamepad_report_buffer ,
+ .report_id = USB_HID_REPORT_ID_GAMEPAD ,
+ .report_length = USB_HID_REPORT_LENGTH_GAMEPAD ,
+ .usage_page = HID_USAGE_PAGE_DESKTOP ,
+ .usage = HID_USAGE_DESKTOP_GAMEPAD ,
+ },
+#endif
+
+#ifdef USB_HID_REPORT_ID_DIGITIZER
+ {
+ .base = { .type = &usb_hid_device_type } ,
+ .report_buffer = digitizer_report_buffer ,
+ .report_id = USB_HID_REPORT_ID_DIGITIZER ,
+ .report_length = USB_HID_REPORT_LENGTH_DIGITIZER ,
+ .usage_page = 0x0D ,
+ .usage = 0x02 ,
+ },
+#endif
+};
+
+
+mp_obj_tuple_t common_hal_usb_hid_devices = {
+ .base = {
+ .type = &mp_type_tuple,
+ },
+ .len = USB_HID_NUM_DEVICES,
+ .items = {
+#if USB_HID_NUM_DEVICES >= 1
+ (mp_obj_t) &usb_hid_devices[0],
+#endif
+#if USB_HID_NUM_DEVICES >= 2
+ (mp_obj_t) &usb_hid_devices[1],
+#endif
+#if USB_HID_NUM_DEVICES >= 3
+ (mp_obj_t) &usb_hid_devices[2],
+#endif
+#if USB_HID_NUM_DEVICES >= 4
+ (mp_obj_t) &usb_hid_devices[3],
+#endif
+#if USB_HID_NUM_DEVICES >= 5
+ (mp_obj_t) &usb_hid_devices[4],
+#endif
+#if USB_HID_NUM_DEVICES >= 6
+ (mp_obj_t) &usb_hid_devices[5],
+#endif
+ }
+};
diff --git a/shared-module/wiznet/__init__.c b/shared-module/wiznet/__init__.c
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/shared-module/wiznet/__init__.c
diff --git a/shared-module/wiznet/wiznet5k.c b/shared-module/wiznet/wiznet5k.c
new file mode 100644
index 000000000..ee732859a
--- /dev/null
+++ b/shared-module/wiznet/wiznet5k.c
@@ -0,0 +1,406 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2014 Damien P. George
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+
+#include "py/objlist.h"
+#include "py/objproperty.h"
+#include "py/runtime.h"
+#include "py/stream.h"
+#include "py/mperrno.h"
+#include "py/mphal.h"
+#include "lib/netutils/netutils.h"
+
+#if MICROPY_PY_WIZNET5K
+
+#include "shared-module/network/__init__.h"
+#include "shared-bindings/digitalio/DigitalInOut.h"
+#include "shared-bindings/digitalio/DriveMode.h"
+#include "shared-bindings/busio/SPI.h"
+
+#include "shared-module/network/__init__.h"
+
+#include "ethernet/wizchip_conf.h"
+#include "ethernet/socket.h"
+#include "internet/dns/dns.h"
+#include "internet/dhcp/dhcp.h"
+
+#include "shared-module/wiznet/wiznet5k.h"
+
+STATIC wiznet5k_obj_t wiznet5k_obj;
+
+STATIC void wiz_cris_enter(void) {
+ wiznet5k_obj.cris_state = MICROPY_BEGIN_ATOMIC_SECTION();
+}
+
+STATIC void wiz_cris_exit(void) {
+ MICROPY_END_ATOMIC_SECTION(wiznet5k_obj.cris_state);
+}
+
+STATIC void wiz_cs_select(void) {
+ common_hal_digitalio_digitalinout_set_value(&wiznet5k_obj.cs, 0);
+}
+
+STATIC void wiz_cs_deselect(void) {
+ common_hal_digitalio_digitalinout_set_value(&wiznet5k_obj.cs, 1);
+}
+
+STATIC void wiz_spi_read(uint8_t *buf, uint32_t len) {
+ (void)common_hal_busio_spi_read(wiznet5k_obj.spi, buf, len, 0);
+}
+
+STATIC void wiz_spi_write(const uint8_t *buf, uint32_t len) {
+ (void)common_hal_busio_spi_write(wiznet5k_obj.spi, buf, len);
+}
+
+int wiznet5k_gethostbyname(mp_obj_t nic, const char *name, mp_uint_t len, uint8_t *out_ip) {
+ uint8_t dns_ip[MOD_NETWORK_IPADDR_BUF_SIZE] = {8, 8, 8, 8};
+ uint8_t *buf = m_new(uint8_t, MAX_DNS_BUF_SIZE);
+ DNS_init(0, buf);
+ mp_int_t ret = DNS_run(dns_ip, (uint8_t*)name, out_ip);
+ m_del(uint8_t, buf, MAX_DNS_BUF_SIZE);
+ if (ret == 1) {
+ // success
+ return 0;
+ } else {
+ // failure
+ return -2;
+ }
+}
+
+int wiznet5k_socket_socket(mod_network_socket_obj_t *socket, int *_errno) {
+ if (socket->u_param.domain != MOD_NETWORK_AF_INET) {
+ *_errno = MP_EAFNOSUPPORT;
+ return -1;
+ }
+
+ switch (socket->u_param.type) {
+ case MOD_NETWORK_SOCK_STREAM: socket->u_param.type = Sn_MR_TCP; break;
+ case MOD_NETWORK_SOCK_DGRAM: socket->u_param.type = Sn_MR_UDP; break;
+ default: *_errno = MP_EINVAL; return -1;
+ }
+
+ if (socket->u_param.fileno == -1) {
+ // get first unused socket number
+ for (mp_uint_t sn = 0; sn < _WIZCHIP_SOCK_NUM_; sn++) {
+ if ((wiznet5k_obj.socket_used & (1 << sn)) == 0) {
+ wiznet5k_obj.socket_used |= (1 << sn);
+ socket->u_param.fileno = sn;
+ break;
+ }
+ }
+ if (socket->u_param.fileno == -1) {
+ // too many open sockets
+ *_errno = MP_EMFILE;
+ return -1;
+ }
+ }
+
+ // WIZNET does not have a concept of pure "open socket". You need to know
+ // if it's a server or client at the time of creation of the socket.
+ // So, we defer the open until we know what kind of socket we want.
+
+ // use "domain" to indicate that this socket has not yet been opened
+ socket->u_param.domain = 0;
+
+ return 0;
+}
+
+void wiznet5k_socket_close(mod_network_socket_obj_t *socket) {
+ uint8_t sn = (uint8_t)socket->u_param.fileno;
+ if (sn < _WIZCHIP_SOCK_NUM_) {
+ wiznet5k_obj.socket_used &= ~(1 << sn);
+ WIZCHIP_EXPORT(close)(sn);
+ }
+}
+
+int wiznet5k_socket_bind(mod_network_socket_obj_t *socket, byte *ip, mp_uint_t port, int *_errno) {
+ // open the socket in server mode (if port != 0)
+ mp_int_t ret = WIZCHIP_EXPORT(socket)(socket->u_param.fileno, socket->u_param.type, port, 0);
+ if (ret < 0) {
+ wiznet5k_socket_close(socket);
+ *_errno = -ret;
+ return -1;
+ }
+
+ // indicate that this socket has been opened
+ socket->u_param.domain = 1;
+
+ // success
+ return 0;
+}
+
+int wiznet5k_socket_listen(mod_network_socket_obj_t *socket, mp_int_t backlog, int *_errno) {
+ mp_int_t ret = WIZCHIP_EXPORT(listen)(socket->u_param.fileno);
+ if (ret < 0) {
+ wiznet5k_socket_close(socket);
+ *_errno = -ret;
+ return -1;
+ }
+ return 0;
+}
+
+int wiznet5k_socket_accept(mod_network_socket_obj_t *socket, mod_network_socket_obj_t *socket2, byte *ip, mp_uint_t *port, int *_errno) {
+ for (;;) {
+ int sr = getSn_SR((uint8_t)socket->u_param.fileno);
+ if (sr == SOCK_ESTABLISHED) {
+ socket2->u_param = socket->u_param;
+ getSn_DIPR((uint8_t)socket2->u_param.fileno, ip);
+ *port = getSn_PORT(socket2->u_param.fileno);
+
+ // WIZnet turns the listening socket into the client socket, so we
+ // need to re-bind and re-listen on another socket for the server.
+ // TODO handle errors, especially no-more-sockets error
+ socket->u_param.domain = MOD_NETWORK_AF_INET;
+ socket->u_param.fileno = -1;
+ int _errno2;
+ if (wiznet5k_socket_socket(socket, &_errno2) != 0) {
+ //printf("(bad resocket %d)\n", _errno2);
+ } else if (wiznet5k_socket_bind(socket, NULL, *port, &_errno2) != 0) {
+ //printf("(bad rebind %d)\n", _errno2);
+ } else if (wiznet5k_socket_listen(socket, 0, &_errno2) != 0) {
+ //printf("(bad relisten %d)\n", _errno2);
+ }
+
+ return 0;
+ }
+ if (sr == SOCK_CLOSED || sr == SOCK_CLOSE_WAIT) {
+ wiznet5k_socket_close(socket);
+ *_errno = MP_ENOTCONN; // ??
+ return -1;
+ }
+ mp_hal_delay_ms(1);
+ }
+}
+
+int wiznet5k_socket_connect(mod_network_socket_obj_t *socket, byte *ip, mp_uint_t port, int *_errno) {
+ // use "bind" function to open the socket in client mode
+ if (wiznet5k_socket_bind(socket, ip, 0, _errno) != 0) {
+ return -1;
+ }
+
+ // now connect
+ MP_THREAD_GIL_EXIT();
+ mp_int_t ret = WIZCHIP_EXPORT(connect)(socket->u_param.fileno, ip, port);
+ MP_THREAD_GIL_ENTER();
+
+ if (ret < 0) {
+ wiznet5k_socket_close(socket);
+ *_errno = -ret;
+ return -1;
+ }
+
+ // success
+ return 0;
+}
+
+mp_uint_t wiznet5k_socket_send(mod_network_socket_obj_t *socket, const byte *buf, mp_uint_t len, int *_errno) {
+ MP_THREAD_GIL_EXIT();
+ mp_int_t ret = WIZCHIP_EXPORT(send)(socket->u_param.fileno, (byte*)buf, len);
+ MP_THREAD_GIL_ENTER();
+
+ // TODO convert Wiz errno's to POSIX ones
+ if (ret < 0) {
+ wiznet5k_socket_close(socket);
+ *_errno = -ret;
+ return -1;
+ }
+ return ret;
+}
+
+mp_uint_t wiznet5k_socket_recv(mod_network_socket_obj_t *socket, byte *buf, mp_uint_t len, int *_errno) {
+ MP_THREAD_GIL_EXIT();
+ mp_int_t ret = WIZCHIP_EXPORT(recv)(socket->u_param.fileno, buf, len);
+ MP_THREAD_GIL_ENTER();
+
+ // TODO convert Wiz errno's to POSIX ones
+ if (ret < 0) {
+ wiznet5k_socket_close(socket);
+ *_errno = -ret;
+ return -1;
+ }
+ return ret;
+}
+
+mp_uint_t wiznet5k_socket_sendto(mod_network_socket_obj_t *socket, const byte *buf, mp_uint_t len, byte *ip, mp_uint_t port, int *_errno) {
+ if (socket->u_param.domain == 0) {
+ // socket not opened; use "bind" function to open the socket in client mode
+ if (wiznet5k_socket_bind(socket, ip, 0, _errno) != 0) {
+ return -1;
+ }
+ }
+
+ MP_THREAD_GIL_EXIT();
+ mp_int_t ret = WIZCHIP_EXPORT(sendto)(socket->u_param.fileno, (byte*)buf, len, ip, port);
+ MP_THREAD_GIL_ENTER();
+
+ if (ret < 0) {
+ wiznet5k_socket_close(socket);
+ *_errno = -ret;
+ return -1;
+ }
+ return ret;
+}
+
+mp_uint_t wiznet5k_socket_recvfrom(mod_network_socket_obj_t *socket, byte *buf, mp_uint_t len, byte *ip, mp_uint_t *port, int *_errno) {
+ uint16_t port2;
+ MP_THREAD_GIL_EXIT();
+ mp_int_t ret = WIZCHIP_EXPORT(recvfrom)(socket->u_param.fileno, buf, len, ip, &port2);
+ MP_THREAD_GIL_ENTER();
+ *port = port2;
+ if (ret < 0) {
+ wiznet5k_socket_close(socket);
+ *_errno = -ret;
+ return -1;
+ }
+ return ret;
+}
+
+int wiznet5k_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) {
+ // TODO
+ *_errno = MP_EINVAL;
+ return -1;
+}
+
+int wiznet5k_socket_settimeout(mod_network_socket_obj_t *socket, mp_uint_t timeout_ms, int *_errno) {
+ // TODO
+ *_errno = MP_EINVAL;
+ return -1;
+
+ /*
+ if (timeout_ms == 0) {
+ // set non-blocking mode
+ uint8_t arg = SOCK_IO_NONBLOCK;
+ WIZCHIP_EXPORT(ctlsocket)(socket->u_param.fileno, CS_SET_IOMODE, &arg);
+ }
+ */
+}
+
+int wiznet5k_socket_ioctl(mod_network_socket_obj_t *socket, mp_uint_t request, mp_uint_t arg, int *_errno) {
+ if (request == MP_STREAM_POLL) {
+ int ret = 0;
+ if (arg & MP_STREAM_POLL_RD && getSn_RX_RSR(socket->u_param.fileno) != 0) {
+ ret |= MP_STREAM_POLL_RD;
+ }
+ if (arg & MP_STREAM_POLL_WR && getSn_TX_FSR(socket->u_param.fileno) != 0) {
+ ret |= MP_STREAM_POLL_WR;
+ }
+ return ret;
+ } else {
+ *_errno = MP_EINVAL;
+ return MP_STREAM_ERROR;
+ }
+}
+
+void wiznet5k_socket_timer_tick(mod_network_socket_obj_t *socket) {
+ if (wiznet5k_obj.dhcp_active) {
+ DHCP_time_handler();
+ DHCP_run();
+ }
+}
+
+void wiznet5k_start_dhcp(void) {
+ static DHCP_INIT_BUFFER_TYPE dhcp_buf[DHCP_INIT_BUFFER_SIZE];
+
+ if (!wiznet5k_obj.dhcp_active) {
+ // Set up the socket to listen on UDP 68 before calling DHCP_init
+ WIZCHIP_EXPORT(socket)(0, MOD_NETWORK_SOCK_DGRAM, DHCP_CLIENT_PORT, 0);
+ DHCP_init(0, dhcp_buf);
+ wiznet5k_obj.dhcp_active = 1;
+ }
+}
+
+void wiznet5k_stop_dhcp(void) {
+ if (wiznet5k_obj.dhcp_active) {
+ wiznet5k_obj.dhcp_active = 0;
+ DHCP_stop();
+ WIZCHIP_EXPORT(close)(0);
+ }
+}
+
+bool wiznet5k_check_dhcp(void) {
+ return wiznet5k_obj.dhcp_active;
+}
+
+/// Create and return a WIZNET5K object.
+mp_obj_t wiznet5k_create(mp_obj_t spi_in, mp_obj_t cs_in, mp_obj_t rst_in) {
+
+ // init the wiznet5k object
+ wiznet5k_obj.base.type = (mp_obj_type_t*)&mod_network_nic_type_wiznet5k;
+ wiznet5k_obj.cris_state = 0;
+ wiznet5k_obj.spi = MP_OBJ_TO_PTR(spi_in);
+ common_hal_digitalio_digitalinout_construct(&wiznet5k_obj.cs, cs_in);
+ common_hal_digitalio_digitalinout_construct(&wiznet5k_obj.rst, rst_in);
+ wiznet5k_obj.socket_used = 0;
+
+ /*!< SPI configuration */
+ // XXX probably should check if the provided SPI is already configured, and
+ // if so skip configuration?
+
+ common_hal_busio_spi_configure(wiznet5k_obj.spi,
+ 10000000, // BAUDRATE 10MHz
+ 1, // HIGH POLARITY
+ 1, // SECOND PHASE TRANSITION
+ 8 // 8 BITS
+ );
+
+ common_hal_digitalio_digitalinout_switch_to_output(&wiznet5k_obj.cs, 1, DRIVE_MODE_PUSH_PULL);
+ common_hal_digitalio_digitalinout_switch_to_output(&wiznet5k_obj.rst, 1, DRIVE_MODE_PUSH_PULL);
+
+ common_hal_digitalio_digitalinout_set_value(&wiznet5k_obj.rst, 0);
+ mp_hal_delay_us(10); // datasheet says 2us
+ common_hal_digitalio_digitalinout_set_value(&wiznet5k_obj.rst, 1);
+ mp_hal_delay_ms(160); // datasheet says 150ms
+
+ reg_wizchip_cris_cbfunc(wiz_cris_enter, wiz_cris_exit);
+ reg_wizchip_cs_cbfunc(wiz_cs_select, wiz_cs_deselect);
+ reg_wizchip_spi_cbfunc(wiz_spi_read, wiz_spi_write);
+
+ // 2k buffer for each socket
+ uint8_t sn_size[16] = {2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2};
+ ctlwizchip(CW_INIT_WIZCHIP, sn_size);
+
+ wiz_NetInfo netinfo = {
+ .dhcp = NETINFO_DHCP,
+ };
+ network_module_create_random_mac_address(netinfo.mac);
+ ctlnetwork(CN_SET_NETINFO, (void*)&netinfo);
+
+ // seems we need a small delay after init
+ mp_hal_delay_ms(250);
+
+ wiznet5k_start_dhcp();
+
+ // register with network module
+ network_module_register_nic(&wiznet5k_obj);
+
+ // return wiznet5k object
+ return &wiznet5k_obj;
+}
+
+#endif // MICROPY_PY_WIZNET5K
diff --git a/shared-module/wiznet/wiznet5k.h b/shared-module/wiznet/wiznet5k.h
new file mode 100644
index 000000000..1284a44fd
--- /dev/null
+++ b/shared-module/wiznet/wiznet5k.h
@@ -0,0 +1,69 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2014 Damien P. George
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef MICROPY_INCLUDED_SHARED_MODULE_WIZNET_WIZNET5K_H
+#define MICROPY_INCLUDED_SHARED_MODULE_WIZNET_WIZNET5K_H
+
+#include "ethernet/wizchip_conf.h"
+#include "ethernet/socket.h"
+#include "internet/dns/dns.h"
+#include "internet/dhcp/dhcp.h"
+
+typedef struct _wiznet5k_obj_t {
+ mp_obj_base_t base;
+ mp_uint_t cris_state;
+ busio_spi_obj_t *spi;
+ digitalio_digitalinout_obj_t cs;
+ digitalio_digitalinout_obj_t rst;
+ uint8_t socket_used;
+ bool dhcp_active;
+} wiznet5k_obj_t;
+
+int wiznet5k_gethostbyname(mp_obj_t nic, const char *name, mp_uint_t len, uint8_t *out_ip);
+int wiznet5k_socket_socket(mod_network_socket_obj_t *socket, int *_errno);
+void wiznet5k_socket_close(mod_network_socket_obj_t *socket);
+int wiznet5k_socket_bind(mod_network_socket_obj_t *socket, byte *ip, mp_uint_t port, int *_errno);
+int wiznet5k_socket_listen(mod_network_socket_obj_t *socket, mp_int_t backlog, int *_errno);
+int wiznet5k_socket_accept(mod_network_socket_obj_t *socket, mod_network_socket_obj_t *socket2, byte *ip, mp_uint_t *port, int *_errno);
+int wiznet5k_socket_connect(mod_network_socket_obj_t *socket, byte *ip, mp_uint_t port, int *_errno);
+mp_uint_t wiznet5k_socket_send(mod_network_socket_obj_t *socket, const byte *buf, mp_uint_t len, int *_errno);
+mp_uint_t wiznet5k_socket_recv(mod_network_socket_obj_t *socket, byte *buf, mp_uint_t len, int *_errno);
+mp_uint_t wiznet5k_socket_sendto(mod_network_socket_obj_t *socket, const byte *buf, mp_uint_t len, byte *ip, mp_uint_t port, int *_errno);
+mp_uint_t wiznet5k_socket_recvfrom(mod_network_socket_obj_t *socket, byte *buf, mp_uint_t len, byte *ip, mp_uint_t *port, int *_errno);
+int wiznet5k_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 wiznet5k_socket_settimeout(mod_network_socket_obj_t *socket, mp_uint_t timeout_ms, int *_errno);
+int wiznet5k_socket_ioctl(mod_network_socket_obj_t *socket, mp_uint_t request, mp_uint_t arg, int *_errno);
+void wiznet5k_socket_timer_tick(mod_network_socket_obj_t *socket);
+mp_obj_t wiznet5k_socket_disconnect(mp_obj_t self_in);
+mp_obj_t wiznet5k_create(mp_obj_t spi_in, mp_obj_t cs_in, mp_obj_t rst_in);
+
+void wiznet5k_start_dhcp(void);
+void wiznet5k_stop_dhcp(void);
+bool wiznet5k_check_dhcp(void);
+
+extern const mod_network_nic_type_t mod_network_nic_type_wiznet5k;
+
+#endif // MICROPY_INCLUDED_SHARED_MODULE_WIZNET_WIZNET5K_H