Skip to content

Instantly share code, notes, and snippets.

@azechi
Last active October 21, 2022 02:57
Show Gist options
  • Save azechi/953414ef03ca6d3df9e036f43ee86745 to your computer and use it in GitHub Desktop.
Save azechi/953414ef03ca6d3df9e036f43ee86745 to your computer and use it in GitHub Desktop.
Raspberry Pi Pico Micropython PWM DMA RING LED fade
from uctypes import *
from machine import Pin, PWM, mem32
# control register structure
DMA_CTRL_LAYOUT = {
"AHB_ERROR": 31<<BF_POS | 1<<BF_LEN | BFUINT32,
"READ_ERROR": 30<<BF_POS | 1<<BF_LEN | BFUINT32,
"WRITE_ERROR": 29<<BF_POS | 1<<BF_LEN | BFUINT32,
"BUSY": 24<<BF_POS | 1<<BF_LEN | BFUINT32,
"SNIFF_EN": 23<<BF_POS | 1<<BF_LEN | BFUINT32,
"BSWAP": 22<<BF_POS | 1<<BF_LEN | BFUINT32,
"IRQ_QUIET": 21<<BF_POS | 1<<BF_LEN | BFUINT32,
"TREQ_SEL": 15<<BF_POS | 6<<BF_LEN | BFUINT32,
"CHAIN_TO": 11<<BF_POS | 4<<BF_LEN | BFUINT32,
"RING_SEL": 10<<BF_POS | 1<<BF_LEN | BFUINT32,
"RING_SIZE": 6<<BF_POS | 4<<BF_LEN | BFUINT32,
"INCR_WRITE": 5<<BF_POS | 1<<BF_LEN | BFUINT32,
"INCR_READ": 4<<BF_POS | 1<<BF_LEN | BFUINT32,
"DATA_SIZE": 2<<BF_POS | 2<<BF_LEN | BFUINT32,
"HIGH_PRIORITY": 1<<BF_POS | 1<<BF_LEN | BFUINT32,
"EN": 0<<BF_POS | 1<<BF_LEN | BFUINT32
}
DMA_BASE = const(0x5000_0000)
# channel offset
DMA_CH = 0x040
# alias CSRs offset address
DMA_0_READ_ADDR = const(0x000)
DMA_0_WRITE_ADDR = const(0x004)
DMA_0_TRANS_COUNT = const(0x008)
DMA_0_CTRL_TRIG = const(0x00c)
DMA_1_TRANS_COUNT_TRIG = const(0x01c)
DMA_3_TRANS_COUNT_READ_ADD_TRIG = const(0x038)
# raw intrrupt status register
DMA_INTR = const(0x400)
PWM_BASE = const(0x4005_0000)
#channel offset (PWM_BASE + (CH * ch) + CC)
PWM_CH = const(0x14)
PWM_CSR = const(0x00) # control and status register
PWM_DIV = const(0x04) # divider
PWM_CTR = const(0x08) # counter
PWM_CC = const(0x0c) # counter compare
PWM_TOP = const(0x10) # counter wrap value
@micropython.viper
def fade():
buff = bytes(4 * 256 * 2)
base = int(ptr(buff))
for i in range(4 * 256):
addr = base + i
if (addr & 0b11_1111_1111) == 0:
break
for i in range(0, 256 * 4, 4):
j = i //4
machine.mem32[addr + i] = uint(j * j << 16)
return buff, addr
fade, fade_addr = fade()
# pwm slice 4
DREQ_PWM_WRAP4 = 28
pwm_ch = PWM_BASE + (PWM_CH * 4)
pwm_cc = pwm_ch + PWM_CC
# PWM slice=4, channel=1
led = PWM(Pin(25))
# clkdiv 8.0
mem32[pwm_ch + PWM_DIV] = (0x8 << 4)
# start pwm
mem32[pwm_ch + PWM_CSR] |= 1
dma_ch = DMA_BASE + (DMA_CH * 2)
ctrl = struct(dma_ch + DMA_0_CTRL_TRIG, DMA_CTRL_LAYOUT)
ctrl.EN = 0
mem32[dma_ch + DMA_0_READ_ADDR] = fade_addr
mem32[dma_ch + DMA_0_WRITE_ADDR] = pwm_cc
mem32[dma_ch + DMA_0_TRANS_COUNT] = 256 * 5 # n * 4 bytes
ctrl.TREQ_SEL = DREQ_PWM_WRAP4
ctrl.CHAIN_TO = 2
ctrl.INCR_WRITE = 0
ctrl.INCR_READ = 1
ctrl.DATA_SIZE = 0x2 # SIZE_WORD: 4 bytes
#ctrl.RING_SEL = 0 # read
ctrl.RING_SIZE = 10
ctrl.EN = 1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment