Initial import - audio output

This commit is contained in:
Jan Hamal Dvořák 2025-06-15 22:02:02 +02:00
commit e634d538bd
7 changed files with 293 additions and 0 deletions

1
.gitignore vendored Normal file
View file

@ -0,0 +1 @@
/build/

3
.gitmodules vendored Normal file
View file

@ -0,0 +1,3 @@
[submodule "src/vendor/pico-stdio-usb-simple"]
path = src/vendor/pico-stdio-usb-simple
url = https://github.com/mordae/pico-stdio-usb-simple

149
etc/regmap.py Normal file
View file

@ -0,0 +1,149 @@
from dataclasses import dataclass
from fnmatch import fnmatch
from sys import argv
from lxml.etree import XML
# List of <peri>.<register> patterns to mark as unsafe.
UNSAFE: list[str] = [
"SIO.SPINLOCK[0-9]*",
"ADC.FIFO",
"SSI.*CR",
"SIO.DIV_QUOTIENT",
"SIO.DIV_REMAINDER",
"SIO.FIFO_RD",
"M0PLUS.SYST_CSR",
"I2C*.IC_CLR*",
"TIMER.TIME[HL]R",
"PIO*.RXF*",
"PPB.*",
"XIP.*",
]
def is_unsafe(peri: str, reg: str) -> bool:
for pattern in UNSAFE:
if fnmatch(f"{peri}.{reg}", pattern):
return True
return False
with open(argv[1], "rb") as fp:
xml = XML(fp.read())
@dataclass
class Register:
name: str
offset: int
reset: int
read: bool
write: bool
@dataclass
class Peripheral:
name: str
base: int
regs: list[Register]
peripherals: dict[str, Peripheral] = {}
for peri in xml.cssselect("peripheral"):
if "derivedFrom" in peri.attrib:
orig = peripherals[peri.attrib["derivedFrom"]]
names = peri.cssselect("peripheral > name")
assert len(names) == 1
peripheral = Peripheral(name=names[0].text, base=orig.base, regs=orig.regs)
continue
names = peri.cssselect("peripheral > name")
assert len(names) == 1
bases = peri.cssselect("peripheral > baseAddress")
assert len(bases) == 1
base = int(bases[0].text, 16)
peripheral = Peripheral(name=names[0].text, base=base, regs=[])
for reg in peri.cssselect("peripheral > registers > register"):
names = reg.cssselect("register > name")
assert len(names) == 1
offsets = reg.cssselect("register > addressOffset")
assert len(offsets) == 1
resets = reg.cssselect("register > resetValue")
assert len(resets) == 1
accesses = reg.cssselect("access")
assert len(accesses) > 0
write = read = False
for access in accesses:
match access.text:
case "read-only":
read = True
case "read-write":
write = read = True
case "write-only":
write = True
case mode:
assert False, f"unknown access mode {mode!r}"
offset = int(offsets[0].text, 16)
reset = int(resets[0].text, 16)
register = Register(
name=names[0].text,
offset=offset,
reset=reset,
write=write,
read=read,
)
peripheral.regs.append(register)
peripherals[peripheral.name] = peripheral
print(
"""
#include "regmap.h"
struct reg_info regmap[] = {
""".strip()
)
for peripheral in peripherals.values():
for register in peripheral.regs:
print("{ ", end="")
print(f"{hex(peripheral.base + register.offset)}, ", end="")
print(f"{hex(register.reset)}, ", end="")
print(f"{hex(register.reset)}, ", end="")
print(f'"{peripheral.name}", ', end="")
print(f'"{register.name}", ', end="")
if register.read:
print("1, ", end="")
else:
print("0, ", end="")
if register.write:
print("1, ", end="")
else:
print("0, ", end="")
if is_unsafe(peripheral.name, register.name):
print("1", end="")
else:
print("0", end="")
print(" },")
print("{ 0, 0, 0, NULL, NULL, 0, 0, 0 },")
print("};")

2
src/.clangd Normal file
View file

@ -0,0 +1,2 @@
CompileFlags:
CompilationDatabase: ../build

49
src/CMakeLists.txt Normal file
View file

@ -0,0 +1,49 @@
cmake_minimum_required(VERSION 3.21)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
include($ENV{PICO_SDK_PATH}/pico_sdk_init.cmake)
project(pdmtest)
pico_sdk_init()
add_executable(pdmtest main.c)
add_subdirectory(vendor/pico-stdio-usb-simple)
target_link_libraries(
pdmtest
pico_stdio_usb_simple
pico_divider
pico_multicore
pico_stdlib
pico_util
hardware_adc
hardware_pwm
hardware_divider
hardware_dma
hardware_pio
hardware_timer
hardware_vreg
)
target_compile_definitions(pdmtest PRIVATE
PLL_SYS_REFDIV=1
PLL_SYS_VCO_FREQ_HZ=1584000000
PLL_SYS_POSTDIV1=6
PLL_SYS_POSTDIV2=2
SYS_CLK_HZ=132000000
)
pico_add_extra_outputs(pdmtest)
set_property(TARGET pdmtest PROPERTY C_STANDARD 23)
target_compile_options(pdmtest PRIVATE -Wall -Wextra -Wnull-dereference)
target_compile_definitions(pdmtest PUBLIC PICO_MAX_SHARED_IRQ_HANDLERS=8u)
target_compile_definitions(pdmtest PUBLIC PICO_STDIO_ENABLE_CRLF_SUPPORT=1)
target_compile_definitions(pdmtest PUBLIC PICO_STDIO_DEFAULT_CRLF=1)
target_include_directories(pdmtest PRIVATE include)
#pico_set_binary_type(pdmtest no_flash)
#pico_set_binary_type(pdmtest copy_to_ram)

88
src/main.c Normal file
View file

@ -0,0 +1,88 @@
#include <pico/stdlib.h>
#include <pico/stdio_usb.h>
#include <hardware/pwm.h>
#include <stdio.h>
#define IR_BIAS_PIN 3
#define IR_RX_PIN 6
#define IR_FB_PIN 7
#define HP_GND_PIN 13
#define HP_LEFT_PIN 14
#define HP_RIGHT_PIN 15
#define HP_GND_SLICE 6
#define HP_GND_CHAN PWM_CHAN_B
#define HP_LR_SLICE 7
#define HP_PWM_RATE (16 * 48 * 1000)
#define HP_PWM_SCALE (SYS_CLK_HZ / HP_PWM_RATE)
#define HP_PWM_MID (HP_PWM_SCALE / 2)
int main()
{
stdio_usb_init();
for (int i = 0; i < 30; i++) {
if (stdio_usb_connected())
break;
sleep_ms(100);
}
printf("\nWelcome to PDM Test!\n");
gpio_disable_pulls(HP_GND_PIN);
gpio_disable_pulls(HP_LEFT_PIN);
gpio_disable_pulls(HP_RIGHT_PIN);
gpio_set_function(HP_GND_PIN, GPIO_FUNC_PWM);
gpio_set_function(HP_LEFT_PIN, GPIO_FUNC_PWM);
gpio_set_function(HP_RIGHT_PIN, GPIO_FUNC_PWM);
gpio_set_drive_strength(HP_GND_PIN, GPIO_DRIVE_STRENGTH_2MA);
gpio_set_drive_strength(HP_LEFT_PIN, GPIO_DRIVE_STRENGTH_2MA);
gpio_set_drive_strength(HP_RIGHT_PIN, GPIO_DRIVE_STRENGTH_2MA);
/* LR at 48 kHz */
pwm_config pc = pwm_get_default_config();
pwm_config_set_clkdiv_int(&pc, 1);
pwm_config_set_phase_correct(&pc, false);
pwm_config_set_wrap(&pc, HP_PWM_SCALE - 1);
pwm_init(HP_LR_SLICE, &pc, false);
/* GND at high rate, 50:50 for virtual ground */
pwm_config_set_wrap(&pc, 1);
pwm_init(HP_GND_SLICE, &pc, false);
pwm_set_chan_level(HP_GND_SLICE, HP_GND_CHAN, 1);
/* Start at 50:50. */
pwm_set_both_levels(HP_LR_SLICE, HP_PWM_MID, HP_PWM_MID);
/* Start both */
pwm_set_enabled(HP_GND_SLICE, true);
pwm_set_enabled(HP_LR_SLICE, true);
while (true) {
for (int i = 0; i < 50; i++) {
sleep_us(2272);
pwm_set_both_levels(HP_LR_SLICE, HP_PWM_MID + 1, HP_PWM_MID + 1);
sleep_us(2272);
pwm_set_both_levels(HP_LR_SLICE, HP_PWM_MID - 1, HP_PWM_MID - 1);
}
for (int i = 0; i < 55; i++) {
sleep_us(2020);
pwm_set_both_levels(HP_LR_SLICE, HP_PWM_MID + 1, HP_PWM_MID + 1);
sleep_us(2020);
pwm_set_both_levels(HP_LR_SLICE, HP_PWM_MID - 1, HP_PWM_MID - 1);
}
sleep_ms(500);
}
}

1
src/vendor/pico-stdio-usb-simple vendored Submodule

@ -0,0 +1 @@
Subproject commit 0897a68ac3ca865715368ce824f49275222ed57e