Initial import - audio output
This commit is contained in:
commit
e634d538bd
7 changed files with 293 additions and 0 deletions
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
/build/
|
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal 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
149
etc/regmap.py
Normal 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
2
src/.clangd
Normal file
|
@ -0,0 +1,2 @@
|
|||
CompileFlags:
|
||||
CompilationDatabase: ../build
|
49
src/CMakeLists.txt
Normal file
49
src/CMakeLists.txt
Normal 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
88
src/main.c
Normal 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
1
src/vendor/pico-stdio-usb-simple
vendored
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit 0897a68ac3ca865715368ce824f49275222ed57e
|
Loading…
Reference in a new issue