Commit Graph

54 Commits

Author SHA1 Message Date
Jim Mussared 94beeabd2e py/obj: Convert make_new into a mp_obj_type_t slot.
Instead of being an explicit field, it's now a slot like all the other
methods.

This is a marginal code size improvement because most types have a make_new
(100/138 on PYBV11), however it improves consistency in how types are
declared, removing the special case for make_new.

Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
2022-09-19 19:06:15 +10:00
Jim Mussared 6da41b5900 py/obj: Merge getiter and iternext mp_obj_type_t slots.
The goal here is to remove a slot (making way to turn make_new into a slot)
as well as reduce code size by the ~40 references to mp_identity_getiter
and mp_stream_unbuffered_iter.

This introduces two new type flags:
- MP_TYPE_FLAG_ITER_IS_ITERNEXT: This means that the "iter" slot in the
  type is "iternext", and should use the identity getiter.
- MP_TYPE_FLAG_ITER_IS_CUSTOM: This means that the "iter" slot is a pointer
  to a mp_getiter_iternext_custom_t instance, which then defines both
  getiter and iternext.

And a third flag that is the OR of both, MP_TYPE_FLAG_ITER_IS_STREAM: This
means that the type should use the identity getiter, and
mp_stream_unbuffered_iter as iternext.

Finally, MP_TYPE_FLAG_ITER_IS_GETITER is defined as a no-op flag to give
the default case where "iter" is "getiter".

Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
2022-09-19 19:06:13 +10:00
Jim Mussared 9dce82776d all: Remove unnecessary locals_dict cast.
Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
2022-09-19 19:06:01 +10:00
Jim Mussared 662b9761b3 all: Make all mp_obj_type_t defs use MP_DEFINE_CONST_OBJ_TYPE.
In preparation for upcoming rework of mp_obj_type_t layout.

Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
2022-09-19 19:06:01 +10:00
Jim Mussared 42587c7870 all: Standardise mp_obj_type_t initialisation.
Remove setting unused slots.

Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
2022-09-19 18:41:29 +10:00
Jim Mussared fb2a57800a all: Simplify buffer protocol to just a "get buffer" callback.
The buffer protocol type only has a single member, and this existing layout
creates problems for the upcoming split/slot-index mp_obj_type_t layout
optimisations.

If we need to make the buffer protocol more sophisticated in the future
either we can rely on the mp_obj_type_t optimisations to just add
additional slots to mp_obj_type_t or re-visit the buffer protocol then.

This change is a no-op in terms of generated code.

Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
2022-09-19 18:40:39 +10:00
David Lechner 8a69c54211 nrf: Use MP_REGISTER_ROOT_POINTER().
This uses MP_REGISTER_ROOT_POINTER() to register all port-specific root
pointers for the nrf port.

Signed-off-by: David Lechner <david@pybricks.com>
2022-07-18 13:50:34 +10:00
Damien George efe23aca71 all: Remove third argument to MP_REGISTER_MODULE.
It's no longer needed because this macro is now processed after
preprocessing the source code via cpp (in the qstr extraction stage), which
means unused MP_REGISTER_MODULE's are filtered out by the preprocessor.

Signed-off-by: Damien George <damien@micropython.org>
2022-06-02 16:31:37 +10:00
Jim Mussared f67ac90fa9 nrf: Make port-specific modules use MP_REGISTER_MODULE.
Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
2022-05-18 20:57:09 +10:00
Jim Mussared 0e7bfc88c6 all: Use mp_obj_malloc everywhere it's applicable.
This replaces occurences of

    foo_t *foo = m_new_obj(foo_t);
    foo->base.type = &foo_type;

with

    foo_t *foo = mp_obj_malloc(foo_t, &foo_type);

Excludes any places where base is a sub-field or when new0/memset is used.

Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
2022-05-03 22:28:14 +10:00
Mike Causer 7f14344428 ports: Add images, features and urls to board.json. 2021-10-28 15:25:38 +11:00
Jim Mussared e359b077dd ports: Add board.json for all boards.
This will be used by https://micropython.org/download/ to generate the
full listing of boards and firmware files.

Optionally supports a board.md for additional customisation of the
download page, as well as deploy.md for flashing instructions.

Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
2021-10-27 14:04:53 +11:00
Glenn Ruben Bakke 55d4321c3e nrf/boards: Enable MICROPY_VFS_LFS2 for all target boards.
Enable LittleFS v2 for all targets, except nrf51 targets when SoftDevice is
present.
2021-08-08 23:17:55 +10:00
Glenn Ruben Bakke ffc636de2f nrf/boards: Set FROZEN_MANIFEST blank when SD present on nrf51 targets. 2021-08-08 23:17:55 +10:00
David Lechner ca920f7218 py/mpstate: Make exceptions thread-local.
This moves mp_pending_exception from mp_state_vm_t to mp_state_thread_t.
This allows exceptions to be scheduled on a specific thread.

Signed-off-by: David Lechner <david@pybricks.com>
2021-06-19 09:43:44 +10:00
Damien George bd54eb566f nrf/boards/microbit: Use mp_sched_exception() where appropriate.
Signed-off-by: Damien George <damien@micropython.org>
2021-04-30 15:13:43 +10:00
Jim Mussared e7f8c7d9a3 nrf: Update to work with nrfx v2.0.0, to match TinyUSB.
Commit 6cea369b89 updated the TinyUSB
submodule to a version based on nrfx v2.0.0.  This commit updates the nrf
port to work with the latest TinyUSB and nrfx v2.0.0.
2020-05-15 15:06:02 +10:00
Damien George 8e048d2548 all: Clean up error strings to use lowercase and change cannot to can't.
Now that error string compression is supported it's more important to have
consistent error string formatting (eg all lowercase English words,
consistent contractions).  This commit cleans up some of the strings to
make them more consistent.
2020-04-13 22:19:37 +10:00
Jim Mussared def76fe4d9 all: Use MP_ERROR_TEXT for all error messages. 2020-04-05 15:02:06 +10:00
Damien George ad9a0ec8ab all: Convert exceptions to use mp_raise_XXX helpers in remaining places. 2020-03-18 17:26:19 +11:00
Damien George ac8383a95d nrf: Use MICROPY_HW_ENABLE_RNG instead of MICROPY_PY_RANDOM_HW_RNG.
The "random" module no longer uses the hardware RNG (the extmod version of
this module has a pseudo-random number generator), so the config option
MICROPY_PY_RANDOM_HW_RNG is no longer meaningful.  This commit replaces it
with MICROPY_HW_ENABLE_RNG, which controls whether the hardware RNG is
included in the build.
2020-02-18 12:43:16 +11:00
Damien George c13f9f209d all: Convert nlr_raise(mp_obj_new_exception_msg(x)) to mp_raise_msg(x).
This helper function was added a while ago and these are the remaining
cases to convert, to save a bit of code size.
2019-11-05 11:35:45 +11:00
Damien George 1fe1ff935b nrf: Clean up source by removing tabs, trailing spaces, non-ASCII chars. 2019-08-28 13:34:45 +10:00
Damien George 7e21cf723a nrf: Change types to size_t for all uses of mp_obj_str_get_data. 2019-05-13 12:39:56 +10:00
Damien George 6e30f96b0b ports: Convert legacy uppercase macro names to lowercase. 2019-02-12 14:54:51 +11:00
Damien George 6ac4304284 nrf/boards/microbit: Use MICROPY_PY_BUILTINS_FLOAT to detect FP support.
This works for both single and double precision float.
2018-07-20 14:11:28 +10:00
Damien George 9addc38af4 nrf: Properly use (void) instead of () for function definitions. 2018-07-20 14:11:28 +10:00
Ayke van Laethem 2f0f4fdcd3
nrf: Use mp_raise_ValueError instead of nlr_raise(...)
Saves 60 bytes on the nRF52 with SD disabled. There will be a bigger
saving with SD enabled and/or on the micro:bit board.
2018-07-18 15:25:17 +02:00
Glenn Ruben Bakke cf58ef27af nrf: Quick-fix on const objects with open array dimension in objtuples.
Temporarly solving the issue of
"differ from the size of original declaration [-Werror=lto-type-mismatch]
until linker is fixed in upcomming release of gcc.

Bug is reported by others, and will be fixed in next version of arm-gcc.
However, this patch makes it possible to use modmusic and modimage
with current compilers.

Alternativly, the code can be compiled with LTO=0, but uses valuable 9K
more on this already squeezed target (microbit).
2018-07-18 17:12:26 +10:00
Glenn Ruben Bakke 0f7da42c75 nrf/modules/random: Rename port config for RNG
Renaming config for enabling random module with hw
random number generator from MICROPY_PY_HW_RNG to
MICROPY_PY_RANDOM_HW_RNG to indicate which module it
is configuring.

Also, disabling the config by default in mpconfigport.h.

Adding the enable of RNG in all board configs.

Moving ifdef in modrandom, which test for the config being
set, earlier in the code. This is to prevent un-necessary
includes if not needed.
2018-07-18 17:12:26 +10:00
Glenn Ruben Bakke 72aacef02e nrf/boards: Remove unused defines from board config headers 2018-07-18 17:12:26 +10:00
Glenn Ruben Bakke 6e8a605500 nrf/modules/machine/pin: Add support for IRQ on Pin's
This patch ads irq method to the pin object. Handlers
registered in the irq method will be kept as part of the
ROOT_POINTERS.

In order to resolve which pin object is the root of the
IRQ, the pin_find has been extended to also be able to
search up Pin objects based on mp_int_t pin number.
This also implies that the Pin.new API is now also supporting
creation of Pin objects based on the integer value of the
pin instead of old style mandating string name of the Pin.

All boards have been updated to use real pin number from
0-48 instead of pin_Pxx for UART/SPI and music module pins.

UART/SPI/modmusic has also been updated to use pin number
provided directly or look up the Pin object based on the
integer value of the pin (modmusic).

Pin generation has been updated to create a list of pins, where
the board/cpu dicts are now refering to an index in this list
instead of having one const declaration for each pin. This new
const table makes it possible to iterate through all pins generated
in order to locate the correct Pin object.
2018-07-18 17:12:26 +10:00
Glenn Ruben Bakke 864f671744 nrf: Remove port member from Pin object
In order to be able to support GPIO1 port on nrf52840
the port has been removed from the Pin object.

All pins on port1 will now be incrementally on top of
the pin numbers for gpio0. Hence, Pin 1.00 will become
P32, and Pin 1.15 will become P47.

The modification is done to address the new gpio HAL
interface in nrfx, which resolves the port to be
configured base on a multiple of 32.

The patch also affects the existing devices which does
not have a second GPIO port in the way that the
port indication A and B is removed from Pin generation.
This means that the port which was earlier addressed
as PA0 is now P0, and PA31 is P31.

Also, this patch removes the gpio member which earlier
pointed to the perihperal GPIO base address. This is not
needed anymore, hence removed.
2018-07-18 17:12:26 +10:00
Ayke van Laethem 2de65dda22 nrf: Make linker scripts more modular.
With all the variation in chips and boards it's tedious to copy and
redefine linker scripts for every option. Making linker scripts more
modular also opens up more possibilities, like enabling/disabling the
flash file system from the Makefile - or even defining it's size from a
Makefile argument (FS_SIZE=12 for a 12kB filesystem if tight on space).
2018-07-18 17:12:26 +10:00
glennrub 002f7d1ad7 nrf: Replace custom-HAL with nrfx-HAL
Summarized this squashed PR replaces the hal/ folder in the port. This has been replaced the official
HAL layer from Nordic Semiconductor; https://github.com/NordicSemiconductor/nrfx.

A Git submodule has been added under lib/nrfx, for the nrfx dependency.

The drivers / modules has been updated to use this new HAL layer; nrfx at v1.0.0.

Also, header files and system files for nrf51/nrf52x chip variants has been deleted from the device/ folder, only keeping back the startup files written in C. All other files are now fetched from nrfx.

3 new header files in the ports/nrf/ folder has been added to configure nrfx (nrfx_config.h), logging (nrfx_log.h) and glue nrfx together with the drivers and modules from micropython (nrfx_glue.h).

The PR has been a joint effort from @aykevl (Ayke van Laethem) and @glennrub.

For reference, the commit log will be kept to get an overview of the changes done:

* ports/nrf: Initial commit for moving hal to Nordic Semiconductor BSD-3 licensed nrfx-hal.

* ports/nrf: Adding nrfx, Nordic Semiconductor BSD-3 hal layer, as git submodule checked out at lib/nrfx.

* ports/nrf/modules/machine/uart: Fixing bug which set hwfc to parity excluded, always resulting in no flow control, hence corrupted output. Also adding an extra loop on uart_tx_char to prevent any tx when any ongoing tx is in progress.

* ports/nrf/i2c: Moving I2C over to nrfx driver.

* ports/nrf/modules/machine/i2c: Alignment. Renaming print function param 'o' to 'self_in'

* ports/nrf/spi: Updating SPI machine module to use nrfx drivers.

* ports/nrf: Renaming modules/machine/rtc.c/.h to rtcounter.c/.h to not confuse the peripheral with Real-Time Clock:

* ports/nrf: Updating various files after renaming machine module RTC to RTCounter.

* ports/nrf: Renaming RTC to RTCounter in modmachine globals dict table. Also updating object type name to reflect new module name.

* ports/nrf: Fixing leftovers after renaming rtc to rtcounter.

* ports/nrf: Early untested adoption of nrfx_rtc in RTCounter. Untested.

* nrf/modules/machine/i2c: Improve keyword argument handling

* ports/nrf/modules/temp: Updating Temp machine module to use nrfx defined hal nrf_temp.h. Moving logic of BLE stack awareness to machine module.

* ports/nrf/boards/pca10040: Enable machine Temp module.

* nrf/modules/machine/rtcounter: Remove magic constants.

* ports/nrf: Adding base support for nrfx module logging. Adding option to disable logging of UART as it might log its own setup over UART while the peripheral is not yet set up. Logging of UART could make sense if other transport of log is used.

* ports/nrf: updating nrfx_log.h with more correct parenthisis on macro grouping.

* ports/nrf: Updating nrfx logging with configuration to disable logging of UART module. The pattern can be used to turn off other modules as well. However, for now UART is the only module locking itself by logging before the peripheral is configured. Logging is turned off by default, can be enabled in nrfx_config.h by setting NRFX_LOG_ENABLED=1.

* ports/nrf/modules/random: Updating modrandom to use nrfx hal for rng. Not using nrfx-driver for this peripheral as its blocking mode would do the trick on RNG. Moving softdevice aware code from legacy hal to modrandom.c.

* nrf: Enable Peripheral Resource Sharing.

This enables TWI and SPI to be enabled at the same time.

* nrf/Makefile: Define MCU sub variant (e.g. NRF51822/NRF51422)

* nrf: Port TIMER peripheral to nrfx HAL.

* nrf/modules/machine/uart: Optimize UART module

For a nRF51, this results in a size reduction of:
.text: -68 bytes
.data: -56 bytes

* nrf/modules/machine/uart: Don't use magic index numbers.

* nrf/modules/machine/uart: Fix off-by-one error.

For nrf51:
.text: -40 bytes

* nrf/modules/machine/rtcounter: Update for nrfx HAL.

* nrf/modules/machine/i2c: Reduce RAM consumption.

Reductions for the nrf51:
flash: -108 bytes
RAM:   -72 bytes

* nrf/mpconfigport: Avoid unnecessary root pointers.

This saves 92 bytes of RAM.

* nrf: Support SoftDevice with nrfx HAL.

* nrf: Add NVMC peripheral (microbitfs) support.

There is no support yet for a SoftDevice.

It also fixes a potentially serious bug in start_index generation.

* nrf/modules/machine/spi: Optimize SPI peripheral.

nrf51:
text: -340 bytes
data: -72  bytes

nrf52:
text: -352 bytes
data: -108 bytes

* nrf/modules/random: Forgot to commit header file.

* nrf: Make nrfx_config.h universal for all boards.

* nrf: Use SoftDevice API for flash access when built for SD

* nrf/drivers/bluetooth: Remove legacy HAL driver includes.

These were not used anymore so can be removed.

* ports/nrf/microbit: Port microbit targets to nrfx HAL

Initial port of microbit modules to use nrfx HAL layer.
Tested display/image and modmusic on micro:bit to verify that
softpwm and ticker for nrf51 is working as expected.

Changing IRQ priority on timer to priority 2, as 1 might collide if
used side by side of SD110 BLE stack.

The patch reserves Timer1 peripheral compile time. This is not ideal
and should be resolved in seperate task.

* nrf/boards/microbit: Remove custom nrfx_config.h from microbit target, adding disablement of timer1 if softpwm is enabled.

* nrf/adc: Update ADC module to use nrfx

* nrf/modules/machine/pwm: Updating machine PWM module to use nrfx HAL driver.

examples/nrf52_pwm.py and examples/nrf52_servo.py tested on pca10040.

* nrf: Removing hal folder and boards nrf5x_hal_conf.h headers.

* nrf/nrfx_glue: Adding direct NVIC access for S110 BLE stack

If SoftDevice s110 has not yet been initialized, the IRQ will not be forwarded to
the application using the sd_nvic* function calls. Hence, direct access to cmsi
nvic functions are used instead if SoftDevice is not enabled.

* nrf/drivers/ticker: Setting IRQ priority 3 on Timer1

SoftDevice fails to initilize if Timer1 has been configured to priority
level 2 before enabling the SD. The timer is set to priority 1, higher than BLE
stack in order to provide better quality of music rendering when used with the
music module. This might be too high, time will show.

* nrf/examples: Updating ubluepy_temp after moving RTCounter to nrfx.

* nrf: delete duplicate files from device folder which can be located in nrfx/mdk.

* nrf/Makefile: Fetch system files from nrfx.

Testing on each device sub-variant to figure out which system file to
use. Reason for this is that nrf52.c is actually defining nrf52832.

Removing NRF_DEFINES parameter setting the device in use into the
same sub-variant test, as NRF52 is unique to nrf52832 when using nrfx.
Without this exclusion of -DNRF52 in compilation for nrf52840, the
device will be interpreted as a nrf52, hence nrf52832.

Also, changing name on variable SRC_NRF_HAL to SRC_NRFX_HAL to
explicitly tell the origin of the file.

* nrf: Updating device #ifdefs to be more open to non-nrf51 targets.

* nrf/modules/machine/uart: Removing second instance of UART for nrf52840 as it only has one non-DMA variant.

* nrf/device: Removing system files as these are now used from nrfx/mdk

* nrf: Moving startup files in device one level up as there is no need for deep hierarchy.

* nrf: Use NRF52_SERIES defined in nrfx/mdk/nrf.h as define value when testing for both nrf52(832) and nrf52840 variants.

* nrf/modules/machine/uart: Enable UART RX by default

Enable rx by default after intiialization of the peripheral.
Else, the nrfx driver will re-enable rx for each byte read
on uart REPL, clearing the EVENT_RXDRDY before second byte,
which again will make second byte get lost and read will get stuck.

This happens if the bytes are transmitted nrf(51) while still
processing the previous byte. Not seen on nrf52, but should
also become an issue at higher speeds.

This patch sets rx to always be enabled. Hence, not clearing the event
between read bytes, and it will be able to detect next byte recieved
upon finishing the first.

* nrf/modules/machine/timer: Fixing defines excluding Timer1 if ticker/softpwm is used.

* nrf: Switching import form mpconfigboard.h to mpconfigport.h in nrfx_config.h as mpconfigboard.h might define default values for defines not set by board specific header.

* nrf/modules/machine/i2c: nrfx integration fixes

Increasing speed to 400K.

Returning Address NACK's as MP error code; MP_ENODEV.

Returning MP_ETIMEOUT on all other error codes from TWI nrfx driver
except the ANACK.

Enabling and disabling the TWI peripheral before and after each transaction.

* nrf/examples: Updating ssd1306_mod.py to split framebuffer transfer into multiple chunks

* nrf/modules/machine/i2c: Return MP_EIO error if Data NACK occurs.

* nrf: Addressing review comments.

* nrf: Updating git submodule and users to nrfx v1.0.0.

* nrf/modules/machine/adc: Update adc module to follow v1.0.0 nrfx API.

* nrf/modules/machine/spi: Implement init and deinit functions

Extending SPI objects with a config member such that
configuration can be kept between new() and init().

Moving initialization done in new() to common init
function shared between the module functions.

If SPI is already configured, the SPI peripheral will
be uninitialized before initalized again.

Adding logic to handle initialization of polarity and
phase. As well, updating default speed to 1M from 500K.

* nrf/modules/machine: Removing unused nrfx includes in machine module header files
2018-07-18 17:12:26 +10:00
Glenn Ruben Bakke 62931398d7 nrf/boards/microbit/modules: Initialize variable in microbit_sleep.
When compiling for microbit with LTO=0, a compiler error occurs due to
'ms' variable in the microbit_sleep function has not been initialized.

This patch initialize the variable to 0.
2018-07-18 17:12:25 +10:00
Ayke van Laethem 4231d4311f nrf: Fix stack size in ld script and enable MICROPY_STACK_CHECK.
The nrf51x22_256k_16k_s110_8.0.0.ld had a stack size of only 1kB, which
is way too low. Additionally, the indicated _minimum_stack_size (set at
2kB for that chip) isn't respected.

This commit sets the heap end based on the stack size (heap end = RAM
end - stack size) making it much easier to configure.

Additionally, the stack/heap size of nrf52 chips has been set to a more
sane value of 8kB.
2018-07-18 17:12:25 +10:00
Ayke van Laethem 987381dfa0 nrf: Make machine.UART optional.
Leave it enabled by default on all targets.

This is only possible when using UART-over-BLE (NUS) instead of the
default hardware peripheral. The flash area saved is quite substantial
(about 2.2KB) so this is useful for custom builds that do not need UART.
2018-07-18 17:12:25 +10:00
Glenn Ruben Bakke c8fd71612b nrf/boards/microbit: Enable music, display, image, microbit module.
Enabled by default on microbit targets, with or without BLE stack.  Also
enable softpwm to make display and music module compile.
2018-07-18 17:12:25 +10:00
Glenn Ruben Bakke 6062d46170 nrf: Change board module header from board_modules.h to boardmodules.h.
Applicable for targets with board specific modules.
2018-07-18 17:12:25 +10:00
Glenn Ruben Bakke 0d7976deb2 nrf/boards/microbit: Update docs on top level tick low pri callback. 2018-07-18 17:12:25 +10:00
Glenn Ruben Bakke 1128aacb69 nrf/boards/microbit: Add temperature back to microbit module.
Increases size by 68 bytes.  Should be considered to be removed as temp
module is already providing this functionality.
2018-07-18 17:12:25 +10:00
Glenn Ruben Bakke b6d01a7dd1 nrf/boards/microbit/modules: Fix tabbing in modmicrobit.c. 2018-07-18 17:12:25 +10:00
Glenn Ruben Bakke 5601fc9397 nrf/boards/microbit: Move microbit target to custom linker script.
To use if BLE stack is enabled.  The custom linker script also set off
space enough to compile in microbitfs+hal_nvmc.
2018-07-18 17:12:25 +10:00
Glenn Ruben Bakke 789f8f1c4b nrf/boards/microbit: Update to work with new ticker code.
- Rename microbit_module_init to board_module_init0 which is the generic
  board module init function.
- Add low priority callback registration of display tick handler in the
  module init function.
2018-07-18 17:12:25 +10:00
Glenn Ruben Bakke d76982e382 nrf/boards/microbit: Include modmicrobit.h in board_modules.h.
So that users of the board module can find the init function of the module
implicitly.
2018-07-18 17:12:25 +10:00
Glenn Ruben Bakke 0b504575e2 nrf/boards/microbit: Add modmicrobit.h to expose module init function. 2018-07-18 17:12:25 +10:00
Glenn Ruben Bakke 1b241be310 nrf/boards/microbit: Attempt to get working display/images without FP.
And update the API to align with new unary/binary function callback
structures.
2018-07-18 17:12:25 +10:00
Glenn Ruben Bakke 9e090a8783 nrf/boards/microbit: Add framework updates to build micro:bit modules.
Makefile and mpconfigport.h update is generic, and could be used by other
boards to give extra modules which are only for a selected board.
2018-07-18 17:12:25 +10:00
Glenn Ruben Bakke fbc45bd3f3 nrf/boards/microbit: Update board modules from C++ to C-code.
This aligns implementation with new style structures.
2018-07-18 17:12:25 +10:00