Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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