Graeme Winter

CircuitPython / uctypes

After enabling uctypes, wanted to see how it works in place if mem32 - it turns out quite well, though could get expensive memory wise with lots of spare dictionaries lying around.

Task

Reproduce the clock wrangling on ItsyBitsy M4 to write out 1kHz square wave to D13. Before, with MicroPython, achieved this with a lot of mem32 calls to set up the GCLK, MCLK, PORT and so on. Here do the same, building structures from the data sheet to facilitate.

Code

import uctypes

PORT = {
    "DIR": 0x0 | uctypes.UINT32,
    "DIRCLR": 0x4 | uctypes.UINT32,
    "DIRSET": 0x8 | uctypes.UINT32,
    "DIRTGL": 0xC | uctypes.UINT32,
    "OUT": 0x10 | uctypes.UINT32,
    "OUTCLR": 0x14 | uctypes.UINT32,
    "OUTSET": 0x18 | uctypes.UINT32,
    "OUTTGL": 0x1C | uctypes.UINT32,
    "IN": 0x20 | uctypes.UINT32,
    "CTRL": 0x24 | uctypes.UINT32,
    "PMUX": (0x30 | uctypes.ARRAY, 16 | uctypes.UINT8),
    "PINCFG": (0x40 | uctypes.ARRAY, 32 | uctypes.UINT8),
}

GCLK = {
    "GENCTRL": (0x20 | uctypes.ARRAY, 12 | uctypes.UINT32),
    "PCHCTRL": (0x80 | uctypes.ARRAY, 48 | uctypes.UINT32),
}

MCLK = {"APBBMASK": 0x18 | uctypes.UINT32}

TCC1 = {
    "CTRLA": 0x0 | uctypes.UINT32,
    "WAVE": 0x3C | uctypes.UINT32,
    "PER": 0x40 | uctypes.UINT32,
    "CC2": 0x4C | uctypes.UINT32,
}

port = uctypes.struct(0x41008000, PORT, uctypes.LITTLE_ENDIAN)
gclk = uctypes.struct(0x40001C00, GCLK, uctypes.LITTLE_ENDIAN)
mclk = uctypes.struct(0x40000800, MCLK, uctypes.LITTLE_ENDIAN)
tcc1 = uctypes.struct(0x41018000, TCC1, uctypes.LITTLE_ENDIAN)

port.PINCFG[22] |= 1
port.PMUX[11] |= 5

gclk.GENCTRL[4] = (0x1 << 16) | (0x1 << 8) | 0x7
gclk.PCHCTRL[25] = (0x1 << 6) | 0x4

mclk.APBBMASK |= 0x1 << 12

tcc1.WAVE = 2
tcc1.PER = 119999
tcc1.CC2 = 60000
tcc1.CTRLA = 2

Sets up struct (not quite minimal, not complete either 🙄) for the main peripherals I want to poke at, then pretty much as before configures them. Output on ‘scope is indeed ~ 1kHz square wave (approximate, because no crystal).

uctypes is a valid replacement, no need really for mem32. Could use this to also cast data from e.g. bytearray to other data types => probably useful.