Skip to content
2 changes: 1 addition & 1 deletion data/nvm.toml
31 changes: 31 additions & 0 deletions ports/raspberrypi/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,32 @@ SRC_CYW43 :=
SRC_LWIP :=
endif

ifeq ($(CIRCUITPY_WIZNET), 1)
INC_WIZNET := \
-isystem common-hal/wiznet \

SRC_WIZNET := \
common-hal/wiznet/wizchip_pio_spi.c \

WIZNET_PIOASM = $(BUILD)/pioasm/pioasm/pioasm
.PHONY: pioasmBuild
pioasmBuild: $(WIZNET_PIOASM)

$(WIZNET_PIOASM):
$(Q)cmake -S pioasm -B $(BUILD)/pioasm
$(MAKE) -C $(BUILD)/pioasm pioasmBuild

$(BUILD)/wizchip_pio_spi.pio.h: common-hal/wiznet/wizchip_pio_spi.pio $(WIZNET_PIOASM)
$(Q)$(WIZNET_PIOASM) -o c-sdk $< $@
$(BUILD)/common-hal/wiznet/wizchip_pio_spi.o: $(BUILD)/wizchip_pio_spi.pio.h

$(BUILD)/genhdr/qstr.i.last: $(BUILD)/wizchip_pio_spi.pio.h

else
INC_WIZNET :=
SRC_WIZNET :=
endif

CHIP_VARIANT_LOWER = $(shell echo $(CHIP_VARIANT) | tr '[:upper:]' '[:lower:]')

INC += \
Expand Down Expand Up @@ -535,6 +561,10 @@ SRC_C += \
bindings/rp2pio/__init__.c \
common-hal/rp2pio/StateMachine.c \
common-hal/rp2pio/__init__.c \
bindings/wiznet/PIO_SPI.c \
bindings/wiznet/__init__.c \
common-hal/wiznet/PIO_SPI.c \
common-hal/wiznet/__init__.c \
audio_dma.c \
background.c \
peripherals/pins.c \
Expand All @@ -544,6 +574,7 @@ SRC_C += \
mphalport.c \
$(SRC_CYW43) \
$(SRC_LWIP) \
$(SRC_WIZNET) \


ifeq ($(CIRCUITPY_USB_HOST), 1)
Expand Down
263 changes: 263 additions & 0 deletions ports/raspberrypi/bindings/wiznet/PIO_SPI.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,263 @@
// This file is part of the CircuitPython project: https://circuitpython.org
//
// SPDX-FileCopyrightText: Copyright (c) 2016 Scott Shawcroft
//
// SPDX-License-Identifier: MIT

// TODO: wiznet.PIO_SPI class.
// This file contains all of the Python API definitions for the
// wiznet.PIO_SPI class.

#include <string.h>

#include "shared-bindings/microcontroller/Pin.h"
#include "bindings/wiznet/PIO_SPI.h"
#include "shared-bindings/util.h"

#include "shared/runtime/buffer_helper.h"
#include "shared/runtime/context_manager_helpers.h"
#include "py/binary.h"
#include "py/mperrno.h"
#include "py/objproperty.h"
#include "py/runtime.h"


// TODO: class WIZNET_PIO_SPI


static mp_obj_t wiznet_pio_spi_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
#if CIRCUITPY_WIZNET
wiznet_pio_spi_obj_t *self = mp_obj_malloc(wiznet_pio_spi_obj_t, &wiznet_pio_spi_type);
#if CIRCUITPY_WIZNET_W6300
enum { ARG_clock, ARG_quad_io0, ARG_quad_io1, ARG_quad_io2, ARG_quad_io3, ARG_half_duplex, ARG_quad_spi };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_clock, MP_ARG_REQUIRED | MP_ARG_OBJ },
{ MP_QSTR_quad_io0, MP_ARG_OBJ, {.u_obj = mp_const_none} },
{ MP_QSTR_quad_io1, MP_ARG_OBJ, {.u_obj = mp_const_none} },
{ MP_QSTR_quad_io2, MP_ARG_OBJ, {.u_obj = mp_const_none} },
{ MP_QSTR_quad_io3, MP_ARG_OBJ, {.u_obj = mp_const_none} },
{ MP_QSTR_half_duplex, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = false} },
};
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);

const mcu_pin_obj_t *clock = validate_obj_is_free_pin(args[ARG_clock].u_obj, MP_QSTR_clock);
const mcu_pin_obj_t *quad_io0 = validate_obj_is_free_pin_or_none(args[ARG_quad_io0].u_obj, MP_QSTR_quad_io0);
const mcu_pin_obj_t *quad_io1 = validate_obj_is_free_pin_or_none(args[ARG_quad_io1].u_obj, MP_QSTR_quad_io1);
const mcu_pin_obj_t *quad_io2 = validate_obj_is_free_pin_or_none(args[ARG_quad_io2].u_obj, MP_QSTR_quad_io2);
const mcu_pin_obj_t *quad_io3 = validate_obj_is_free_pin_or_none(args[ARG_quad_io3].u_obj, MP_QSTR_quad_io3);

common_hal_wiznet_pio_qspi_construct(self, clock, quad_io0, quad_io1, quad_io2, quad_io3, args[ARG_half_duplex].u_bool);

#else // W55RP20
enum { ARG_clock, ARG_MOSI, ARG_MISO, ARG_half_duplex };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_clock, MP_ARG_REQUIRED | MP_ARG_OBJ },
{ MP_QSTR_MOSI, MP_ARG_OBJ, {.u_obj = mp_const_none} },
{ MP_QSTR_MISO, MP_ARG_OBJ, {.u_obj = mp_const_none} },
{ MP_QSTR_half_duplex, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = false} },
};
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);

const mcu_pin_obj_t *clock = validate_obj_is_free_pin(args[ARG_clock].u_obj, MP_QSTR_clock);
const mcu_pin_obj_t *mosi = validate_obj_is_free_pin_or_none(args[ARG_MOSI].u_obj, MP_QSTR_mosi);
const mcu_pin_obj_t *miso = validate_obj_is_free_pin_or_none(args[ARG_MISO].u_obj, MP_QSTR_miso);

if (!miso && !mosi) {
mp_raise_ValueError(MP_ERROR_TEXT("Must provide MISO or MOSI pin"));
}

common_hal_wiznet_pio_spi_construct(self, clock, mosi, miso, args[ARG_half_duplex].u_bool);
#endif
return MP_OBJ_FROM_PTR(self);
#else
mp_raise_NotImplementedError(NULL);
#endif // CIRCUITPY_WIZNET
}

#if CIRCUITPY_WIZNET

// TODO: def deinit

static mp_obj_t wiznet_pio_spi_obj_deinit(mp_obj_t self_in) {
wiznet_pio_spi_obj_t *self = MP_OBJ_TO_PTR(self_in);
common_hal_wiznet_pio_spi_deinit(self);
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_1(wiznet_pio_spi_deinit_obj, wiznet_pio_spi_obj_deinit);

// TODO: def __enter__

// TODO: def __exit__

static void check_lock(wiznet_pio_spi_obj_t *self) {
asm ("");
if (!common_hal_wiznet_pio_spi_has_lock(self)) {
mp_raise_RuntimeError(MP_ERROR_TEXT("Function requires lock"));
}
}

static void check_for_deinit(wiznet_pio_spi_obj_t *self) {
if (common_hal_wiznet_pio_spi_deinited(self)) {
raise_deinited_error();
}
}

// TODO: def configure

static mp_obj_t wiznet_pio_spi_configure(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_baudrate, ARG_polarity, ARG_phase, ARG_bits };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_baudrate, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 100000} },
{ MP_QSTR_polarity, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
{ MP_QSTR_phase, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
{ MP_QSTR_bits, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 8} },
};
wiznet_pio_spi_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
check_for_deinit(self);
check_lock(self);
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);

uint8_t polarity = (uint8_t)mp_arg_validate_int_range(args[ARG_polarity].u_int, 0, 1, MP_QSTR_polarity);
uint8_t phase = (uint8_t)mp_arg_validate_int_range(args[ARG_phase].u_int, 0, 1, MP_QSTR_phase);
uint8_t bits = (uint8_t)mp_arg_validate_int_range(args[ARG_bits].u_int, 8, 9, MP_QSTR_bits);

if (!common_hal_wiznet_pio_spi_configure(self, args[ARG_baudrate].u_int,
polarity, phase, bits)) {
mp_raise_OSError(MP_EIO);
}
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_KW(wiznet_pio_spi_configure_obj, 1, wiznet_pio_spi_configure);

// TODO: def try_lock

static mp_obj_t wiznet_pio_spi_obj_try_lock(mp_obj_t self_in) {
wiznet_pio_spi_obj_t *self = MP_OBJ_TO_PTR(self_in);
return mp_obj_new_bool(common_hal_wiznet_pio_spi_try_lock(self));
}
MP_DEFINE_CONST_FUN_OBJ_1(wiznet_pio_spi_try_lock_obj, wiznet_pio_spi_obj_try_lock);

// TODO: def unlock

static mp_obj_t wiznet_pio_spi_obj_unlock(mp_obj_t self_in) {
wiznet_pio_spi_obj_t *self = MP_OBJ_TO_PTR(self_in);
check_for_deinit(self);
common_hal_wiznet_pio_spi_unlock(self);
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_1(wiznet_pio_spi_unlock_obj, wiznet_pio_spi_obj_unlock);

// TODO: def write

static mp_obj_t wiznet_pio_spi_write(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_buffer, ARG_start, ARG_end };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_buffer, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
{ MP_QSTR_start, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
{ MP_QSTR_end, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = INT_MAX} },
};

wiznet_pio_spi_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
check_for_deinit(self);
check_lock(self);
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);

mp_buffer_info_t bufinfo;
mp_get_buffer_raise(args[ARG_buffer].u_obj, &bufinfo, MP_BUFFER_READ);
// Compute bounds in terms of elements, not bytes.
int stride_in_bytes = mp_binary_get_size('@', bufinfo.typecode, NULL);
int32_t start = args[ARG_start].u_int;
size_t length = bufinfo.len / stride_in_bytes;
normalize_buffer_bounds(&start, args[ARG_end].u_int, &length);

// Treat start and length in terms of bytes from now on.
start *= stride_in_bytes;
length *= stride_in_bytes;

if (length == 0) {
return mp_const_none;
}

bool ok = common_hal_wiznet_pio_spi_write(self, ((uint8_t *)bufinfo.buf) + start, length);

if (!ok) {
mp_raise_OSError(MP_EIO);
}
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_KW(wiznet_pio_spi_write_obj, 1, wiznet_pio_spi_write);

// TODO: def readinto

static mp_obj_t wiznet_pio_spi_readinto(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_buffer, ARG_start, ARG_end, ARG_write_value };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_buffer, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
{ MP_QSTR_start, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
{ MP_QSTR_end, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = INT_MAX} },
{ MP_QSTR_write_value, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
};
wiznet_pio_spi_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
check_for_deinit(self);
check_lock(self);
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);

mp_buffer_info_t bufinfo;
mp_get_buffer_raise(args[ARG_buffer].u_obj, &bufinfo, MP_BUFFER_WRITE);
// Compute bounds in terms of elements, not bytes.
int stride_in_bytes = mp_binary_get_size('@', bufinfo.typecode, NULL);
int32_t start = args[ARG_start].u_int;
size_t length = bufinfo.len / stride_in_bytes;
normalize_buffer_bounds(&start, args[ARG_end].u_int, &length);

// Treat start and length in terms of bytes from now on.
start *= stride_in_bytes;
length *= stride_in_bytes;

if (length == 0) {
return mp_const_none;
}

bool ok = common_hal_wiznet_pio_spi_read(self, ((uint8_t *)bufinfo.buf) + start, length, args[ARG_write_value].u_int);
if (!ok) {
mp_raise_OSError(MP_EIO);
}
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_KW(wiznet_pio_spi_readinto_obj, 1, wiznet_pio_spi_readinto);

#endif // CIRCUITPY_WIZNET

static const mp_rom_map_elem_t wiznet_pio_spi_locals_dict_table[] = {
#if CIRCUITPY_WIZNET
{ MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&wiznet_pio_spi_deinit_obj) },
{ MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) },
{ MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&default___exit___obj) },

{ MP_ROM_QSTR(MP_QSTR_configure), MP_ROM_PTR(&wiznet_pio_spi_configure_obj) },
{ MP_ROM_QSTR(MP_QSTR_try_lock), MP_ROM_PTR(&wiznet_pio_spi_try_lock_obj) },
{ MP_ROM_QSTR(MP_QSTR_unlock), MP_ROM_PTR(&wiznet_pio_spi_unlock_obj) },

{ MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&wiznet_pio_spi_readinto_obj) },
{ MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&wiznet_pio_spi_write_obj) },

#endif // CIRCUITPY_WIZNET
};
static MP_DEFINE_CONST_DICT(wiznet_pio_spi_locals_dict, wiznet_pio_spi_locals_dict_table);

MP_DEFINE_CONST_OBJ_TYPE(
wiznet_pio_spi_type,
MP_QSTR_PIO_SPI,
MP_TYPE_FLAG_NONE,
make_new, wiznet_pio_spi_make_new,
locals_dict, &wiznet_pio_spi_locals_dict
);

wiznet_pio_spi_obj_t *validate_obj_is_wiznet_pio_spi_bus(mp_obj_t obj, qstr arg_name) {
return mp_arg_validate_type(obj, &wiznet_pio_spi_type, arg_name);
}
47 changes: 47 additions & 0 deletions ports/raspberrypi/bindings/wiznet/PIO_SPI.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// This file is part of the CircuitPython project: https://circuitpython.org
//
// SPDX-FileCopyrightText: Copyright (c) 2016 Scott Shawcroft
//
// SPDX-License-Identifier: MIT

#pragma once

#include "py/obj.h"

#include "common-hal/microcontroller/Pin.h"
#include "common-hal/wiznet/PIO_SPI.h"

// Type object used in Python. Should be shared between ports.
extern const mp_obj_type_t wiznet_pio_spi_type;

#if CIRCUITPY_WIZNET_W6300

extern void common_hal_wiznet_pio_qspi_construct(wiznet_pio_spi_obj_t *self,
const mcu_pin_obj_t *clock, const mcu_pin_obj_t *quad_io0,
const mcu_pin_obj_t *quad_io1, const mcu_pin_obj_t *quad_io2,
const mcu_pin_obj_t *quad_io3, bool half_duplex);

#else // W55RP20
// Construct an underlying SPI object.
extern void common_hal_wiznet_pio_spi_construct(wiznet_pio_spi_obj_t *self,
const mcu_pin_obj_t *clock, const mcu_pin_obj_t *mosi,
const mcu_pin_obj_t *miso, bool half_duplex);

#endif

extern void common_hal_wiznet_pio_spi_deinit(wiznet_pio_spi_obj_t *self);
extern bool common_hal_wiznet_pio_spi_deinited(wiznet_pio_spi_obj_t *self);

extern bool common_hal_wiznet_pio_spi_configure(wiznet_pio_spi_obj_t *self, uint32_t baudrate, uint8_t polarity, uint8_t phase, uint8_t bits);

extern bool common_hal_wiznet_pio_spi_try_lock(wiznet_pio_spi_obj_t *self);
extern bool common_hal_wiznet_pio_spi_has_lock(wiznet_pio_spi_obj_t *self);
extern void common_hal_wiznet_pio_spi_unlock(wiznet_pio_spi_obj_t *self);

// Writes out the given data.
extern bool common_hal_wiznet_pio_spi_write(wiznet_pio_spi_obj_t *self, const uint8_t *data, size_t len);

// Reads in len bytes while outputting the byte write_value.
extern bool common_hal_wiznet_pio_spi_read(wiznet_pio_spi_obj_t *self, uint8_t *data, size_t len, uint8_t write_value);

extern wiznet_pio_spi_obj_t *validate_obj_is_wiznet_pio_spi_bus(mp_obj_t obj_in, qstr arg_name);
29 changes: 29 additions & 0 deletions ports/raspberrypi/bindings/wiznet/__init__.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// This file is part of the CircuitPython project: https://circuitpython.org
//
// SPDX-FileCopyrightText: Copyright (c) 2016 Scott Shawcroft for Adafruit Industries
//
// SPDX-License-Identifier: MIT

#include <stdint.h>

#include "py/obj.h"
#include "py/runtime.h"

#include "shared-bindings/microcontroller/Pin.h"
#include "bindings/wiznet/PIO_SPI.h"

#include "py/runtime.h"

static const mp_rom_map_elem_t wiznet_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_wiznet) },
{ MP_ROM_QSTR(MP_QSTR_PIO_SPI), MP_ROM_PTR(&wiznet_pio_spi_type) },
};

static MP_DEFINE_CONST_DICT(wiznet_module_globals, wiznet_module_globals_table);

const mp_obj_module_t wiznet_module = {
.base = { &mp_type_module },
.globals = (mp_obj_dict_t *)&wiznet_module_globals,
};

MP_REGISTER_MODULE(MP_QSTR_wiznet, wiznet_module);
Loading
Loading